原创 【博客大赛】基于LCD12864显示器的数字示波器设计

2012-4-9 22:56 2635 8 12 分类: 测试测量

文针对LCD12864 特性,完成了数字示波器显示必须的绘图驱动程序设计,这个教程定位给初学者使用,立足从简单到复杂一步一步介绍设计过程,甚至是调试的过程,还包括一些经验总结,特别是提供了完整的keil 工程附件。希望读者立足示波器项目,学到更多软硬件设计经验技巧。
 

  一、简易数字示波器原理


 

  数字示波器基本原理可以简单理解为:数据采集+ 图形显示,该过程循环进行,如图1 所示。


 

   attachimg.gif 091247l06ffll3l2rpnrpe.jpg

 

下载 (9.38 KB)

 



图1 简易数字示波器流程图
 

  LCD 图形显示需要根据LCD 特性设计,不同LCD驱动程序不同,本篇将结合不带字库的LCD12864 设计显示程序。


 

  二、图形液晶LCD12864绘图驱动设计基础


 

  关于LCD 的硬件接口电路,在其他教程中有详细介绍,涉及单片机总线知识和CPLD 内部电路,需要认真学习,这里借助现成的驱动函数,重点讲解LCD绘图程序设计。


 

  LCD12864 的电路接口在头文件中定义:


 

  #define LCD_LCW XBYTE[0xf4ea]


 

  // 左屏命令写入


 

  #define LCD_LDW XBYTE[0xf5ea]


 

  // 左屏数据写入


 

  #define LCD_LCR XBYTE[0xf6ea]


 

  // 左屏命令读出


 

  #define LCD_LDR XBYTE[0xf7ea]


 

  // 左屏数据读出


 

  #define LCD_RCW XBYTE[0xf8ea]


 

  // 右屏命令写入


 

  #define LCD_RDW XBYTE[0xf9ea]


 

  // 右屏数据写入


 

  #define LCD_RCR XBYTE[0xfaea]


 

  // 右屏命令读出


 

  #define LCD_RDR XBYTE[0xfbea]


 

  // 右屏数据读出


 

  后面所有对LCD 的编程操作都是基于以上接口定义进行的各种读写操作。


 

  首先来看LCD12864 的点阵结构图,如图2 所示。


 

   attachimg.gif 091247ab8ebb8affam98n4.jpg

 

下载 (38.7 KB)

 



图2 LCD点阵分布结构图
 

  此LCD 屏由水平128 列,垂直64 行组成。水平128 列分左右各64 列两个半屏构成。垂直64 行又分8 页,每页8 行(1 列8 点刚好1 字节)。程序每次对LCD 的绘图操作就是以最小单位1 字节进行操作的。


 

  理解这点至关重要。也就是每次只能针对8 点进行操作,而不是1 点进行操作。左右屏由单独地址线控制(前面的接口定义就是分左右屏定义的)。实际打点只需往指定“位置”写入数据,“1”亮,“0”暗。


 

  LCD 驱动忙检测函数void loop_lcd12864_is_busy(unsigned char right)。


 

  void loop_lcd12864_is_busy(unsigned char right)


 

  {


 

  unsigned char tmp,counter=0;


 

  do {


 

  if(right) tmp = LCD_RCR;


 

  else tmp = LCD_LCR;


 

  if(counter++>50) break; // 超时跳出


 

  }


 

  while ((tmp|0x7f)==0xff); //bit7 为1 则表示LCD 内部执行命令,处于“忙”状态


 

  }


 

  对LCD 进行读写操作时,需要进行“忙”检测,LCD 内部也是由控制器来完成一系列刷屏操作的,执行各种操作都是需要一定的时间,也就是说不是任何时候外部控制器都可以对LCD 发操作指令的,只有LCD为空闲状态时才可以操作,忙检测就是循环读取LCD状态标志位,判断是否空闲,关于命令的细节请参考数据手册。


 

  命令写入函数void lcd_cmd_wr(unsigned char cmd,right)。


 

  void lcd_cmd_wr(unsigned char cmd, right)


 

  {


 

  loop_lcd12864_is_busy(right); // 忙检测


 

  if(right) LCD_RCW = cmd; // 右屏命令写入


 

  else LCD_LCW = cmd; // 左屏命令写入


 

  }


 

  数据写入函数void lcd_dat_wr(unsigned char data,right)。


 

  void lcd_dat_wr(unsigned char data,right)


 

  {


 

  loop_lcd12864_is_busy(right);


 

  if(right) LCD_RDW = data;


 

  else LCD_LDW = data;


 

  }


 

  lcd_cmd_wr() 和lcd_dat_wr() 两个函数分别是给LCD 写命令和写数据函数,通过写命令函数设定地址。每个函数都分左右屏,“right”参数选择,“0”选左屏,“非0”选右屏。


 

  读数据函数unsigned char lcd_dat_rd(unsigned char right)。


 

  unsigned char lcd_dat_rd(unsigned char right)


 

  {


 

  loop_LCD12864_is_busy(right);


 

 

  六、数字示波器几个参数


  1. 数据采样率与时间轴定标


  数据采样率也就是每秒钟连续采集到的数据个数,或者说两个有效数据之间的时间间隔。为了在LCD 上还原波形图,时间轴与采样率之间要有严格的换算关系。


  为了还原波形图,采样率与被测量信号频率之间有一定的关联,不同的采样率,对应不同频段的信号,高采样率适合高频信号,低采样率适合变化缓慢的低频信号。


  从显示效果来看,为了在屏幕上再现信号的频率特征,根据Nyquist 频率特征定理,一般要保证信号的每个周期内至少有2 点,用LCD 再现,2 点效果已经很差了。最高采样率一般由ADC 器件决定,这里用的TLC1549 最快只能做到88μs 采集一点,按2 点每周期计算的话,可以做到对5.6K(1000000/88/2) 信号采样,实际效果已经很差了,1K 以内效果最好。


  实际在设计采样率档位时,最快档按100μs 每点,屏幕每5 点(500μs)一格,第一档就是0.5ms/div,这一档位需要连续采样,用少量延时控制采样率为10k,第二档就是1ms/div,第三档2ms/div,第四档5ms/div,第五档10ms/div,后面四档分别用定时器控制完成。


  2. 电压轴分档定标


  由于这版没做模拟电路,没有信号电调理电路,所谓电压档定标是纯软件算法实现,屏幕同样取5 点一格,共10 格,当输入信号从0 到5V 变化时,LCD 刚好满屏显示,每格0.5V,另外还设计了0.1v/div,0.2v/div,1v/div,2v/div,5v/div。共6 档。


  3. 交流直流切换


  功能完善的示波器应该从硬件上实现交直流切换,本版先从软件上实现交流直流显示,设计思想是根据采样得到的数据的最大值和最小值确定交流信号幅度和中值,把直流部分减掉,显示只显示交流部分,这就是交流档,直流档就是不做去直流处理。


  4. 运行停止切换


  该功能实现起来很容易,所谓停止,就是停止新的数据采集,重复显示同一帧数据,显示的效果就是波形稳定无抖动,便于对信号电压和频率进行测量。


  5. 电压测量


  根据当前电压档位(每格表示多少伏),计算出两测量线之间的电压值,在LCD 上显示。


  6. 频率测量


  根据当前时间轴档位(每格表示多长时间),计算出两测量线之间的时间,假定两测量线之间刚好是一个周期,转换成频率值在LCD 上显示。


  7. 波形平移


  用变量控制波形在LCD 上显示的相对位置,实现波形上下左右平移。


  8. 帧同步


  我们使用的数字示波器,对有规律的周期信号能够稳定显示,要想实现稳定显示,需要在起始点显示信号的不同周期的同一点,如何做到这点呢?

  我们对比两帧数据,波形起点不在同一点,我们没办法保证每次数据采样刚好在同一点(硬件触发的除外),我需要按一定的规律,在LCD 上绘图时,总是从同一点开始,例如过零点,这里我们首先用统计的办法找出信号的最大值和最小值,计算出信号中交流部分的中点,也就是过零点,然后逐点比较,搜寻过零点。

   091418qrhe2ryx2bede5hw.jpg

下载 (7.96 KB)

 



图10 不同帧数据起点不同

  程序设计思想是逐点比较过滤,我们取中值,如图7-1 中第5 点所示,信号从小于中值到大于中值的上升沿为起点,不同帧信号可能从1、2、3、4 任何一点开始,这就要用程序判断把设定的起点5 以前的数据丢掉。


  程序是这样的:


  while(da_buffer > dam) if(++i > (DATA_SIZE/2)) break;


  while(da_buffer <= dam) if(++i > (DATA_SIZE/2)) break;


  while(da_buffer > dam) if(++i > (DATA_SIZE/2)) break;


  这里的dam 就是信号交流部分的中值。


  程序用几个while 语句,看上去很呆板,实际运行效果很好喔。第一句把比设定值大的数据过滤,如图10 中的1、2、3 点,如果数据是从4 开始的,第一句会直接跳过;第二句把比设定值小的数据跳过,找出过零点的上升沿5 点。

PARTNER CONTENT

文章评论4条评论)

登录后参与讨论

用户377235 2015-10-25 21:54

Inaoimftron is power and now I'm a !@#$ing dictator.

用户419124 2012-5-11 19:46

嗯,图文并茂,不错不错~~

飞言走笔 2012-5-3 08:20

嗯,不错不错~~

用户377235 2012-4-29 11:37

学习学习
相关推荐阅读
用户1647968 2013-03-12 22:27
[博客大赛]TI官网上的WEBENCH® Power Designer 设计工具厉害啊
您指掌之间完成电源设计! WEBENCH设计环境为您提供了创建电源或直流/直流转换器所需的全面设计和原型建立工具,能够有效地满足您的设计要求。WEBENCH工具让设计者在建...
用户1647968 2013-03-12 21:53
【博客大赛】【原创】基于ALTER 数字信号传输性能分析仪
...
用户1647968 2012-11-22 12:20
【TI博客大赛】基于TMS320LF2407A的PMSM矢量控制电流环的设计
三相永磁同步电动机的转矩方程为 (4-1) 上式说明了转矩由两项组成,括号中的第一项是由三相旋转磁场和永磁磁场相互作用所产生的电磁转矩;第二项是由凸极效应引起的磁阻转矩。 对于嵌入式转子,Ld,电磁转...
用户1647968 2012-11-22 12:18
【TI博客大赛】基于DSP28027的SVPWM简易变频器
SVPWM技术的原理 2.1 基本电压空间矢量 图1示出电动游览车的逆变器主电路。规定当上桥臂的一个开关管导通时,开关状态为1。此时,相应的下桥臂开关管关断;反之亦然,开关状态为0。3个桥...
用户1647968 2012-08-25 22:37
【TI博客大赛】TI电源管理芯片BQ20Z75DBT 设计高稳定笔记本电池移动电源
时间岁月飞快啊,一转眼俺做电源工程师之路也有10年了,一直做移动笔记本电池电源设计,使用过不少笔记本电源设计应用解决方案。说起使用稳定性,也很纠结啊,笔记本电源安全性一直各品牌生产厂家最关注问题,经过...
用户1647968 2012-08-25 22:34
【TI博客大赛】基于TI DSP的数字化三相变频电源的研制
    随着电力电子技术的飞速发展,正弦波输出变频电源已被广泛应用在各个领域中,与此同时对变频电源的输出电压波形质量也提出了越来越高的要求。在实验室和工业部门,三相正弦波变频电源常用于各种测量和控...
EE直播间
更多
我要评论
4
8
关闭 站长推荐上一条 /3 下一条