基于51单片机数字示波器设计
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
//清空接受标志位 //清空发送标志位
}
往串口写 1 字节函数 void uart_put_uchar(unsigned char c)。 void uart_put_uchar(unsigned char c) //往串口写 1 字节无符号数据 {
SBUF = c; while(!TI); TI = 0; }
图 2-1 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) {
ADC_CK = 0;
temp <<= 1;
if(ADC_DA) temp++;
ADC_CK = 1;
}
ADC_CS = 1;
return(temp);
}
注:带背景色的源码都是直接从演示程序中拷贝的。
以上是是驱动 TLC1549 的函数,如果你还想彻底弄清 TLC1549 的各种参数,请参考数据手册 TLC1549.pdf,使用该函数需要注意的是,两次调用该函数之间的间隔要超过 21us,AD 转换是要一
图 1-1 简易数字示波器流程图
read_adc(void)。
unsigned int read_adc(void)
{
unsiΒιβλιοθήκη Baiduned char i;
unsigned int temp=0; ADC_CS = 0; //开启控制电路,使能 DA 和 CK IO 引脚 for(i=0;i<10;i++) { //采集 10 次 ,即 10bit
主程序这样改: #include "mini51b.n" //所有与硬件相关的接口函数定义 #include "uart.h" void main() {
rs232_port_init(); read_adc(); delay_ms(1); while(1) {
uart_put_uchar(read_adc()/4); //seg7_disp(read_adc()); delay_ms(1); //这里的延时起到调节采样率的作用 } } 运行【MyOsc】,设置串口和波特率后“OPEN”,适当调节输入信号频率后可以看到如图 1-3 所 示的图案。
unsigned char code tab1[20]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,}; unsigned char temp,flag=0; if(number < 10000) {
temp = number/1000%10; //千位数码管 if (temp) {
1 简易数字示波器原理
数字示波器基本原理可以简单理解为:数据
采集+图形显示,该过程循环进行,如图 1-1 所
示。
首先是数据采集,这一版我们直接用 Mini51 板上的 ADC“TLC1549”。(如果你没有 ADC,
也可能没有信号发生器,后面会介绍一种正弦表
调试方法。)
TLC1549 驱 动 函 数 unsigned int
图 1-3 串口绘图软件示例
第 4 页,共 34 页
运行【ComCalWave】,选择正确的串口号和波特率,“Open COM”,再设置“Wave Show”,看 到了什么?图形!在图形窗口尝试用鼠标右键操作,还可选择特定范围显示,如图 1-4 所示。
图 1-4 串口绘图软件示例 2 要看到以上漂亮的波形,还有一些硬件连接要做,需要将信号发生器和 Mini51 板上 ADCin 接 口连接,注意,TLC1549 只能进行 0 到 5V 之间的信号转换,你还需要调整信号发生器,产生满足 条件的信号才行。 以上演示源程序 keil 工程请参考附件【串口调试 2】 实际在调试程序中,缺少必要硬件设备的,还可以用正弦表代替实际 ADC,这里再介绍一款正 弦表生成器软件【正弦表发生器】,软件界面如图 1-5 所示。
基于 Mini51 板硬件资源,构思数字示波器的方案已经思考很久了,总是没有集中的时间,一个 稍微复杂的设计完成创作需要集中的时间才能完成,这次利用学期结束的一段集中时间,完成了基 于 LCD12864 显示的数字示波器程序设计,现在将文档写出来供大家交流学习用。在此声明,这个 教程是写给初学者看的,我会从简单到复杂一步一步详细介绍设计过程,甚至是调试的过程,还包 括一些经验总结,特别是提供了完整的 keil 工程附件。希望读者立足示波器项目,学到更多关于软 硬件开发的一些经验技巧。
第 6 页,共 34 页
2 图形液晶 LCD12864 绘图驱动设计基础
下面我们学习如何在 LCD12864 上显示同样的正弦波形。 关于 LCD 的硬件接口电路,在前面的教程中有详细介绍,涉及单片机总线知识和 CPLD 内部电 路,需要专门学习,这里我们借助现成的驱动函数,重点讲解 LCD 绘图程序设计。 LCD12864 的电路接口在【mini51b.h】头文件中定义。 #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 的编程操作都是基于以上接口定义(总线编址)进行的读写操作。 首先来看 LCD 点阵结构图,这里以不带字库的 LCD12864 来讲解,如图 2-1 所示。
while(1) {
if(uart_get_uchar()==0x55) uart_put_uchar(read_adc()/4); //10bit/4 变 8bit
}
}
在主程序循环中,接收到上位机下发的数据 0x55 后,读取 ADC 数据并发送一次,在串口调试
助手(例如 SSCOM)里,设置相关端口和波特率后,发送 0x55,注意 HEX(十六进制格式)选项, 就可以看到 ADC 的结果,如图 1-2 所示。
段时间的,在高速系统中时间控制尤其关键。Mini51 板单片机在 22.1184M 晶振时钟频率下运行, 连续两次 AD 采集数据并将数据写入外部扩展 RAM 变量缓冲区,之间的时间间隔实测略小于 21us 的,需要适当延时。这在高速档数据采集时增加了一定延时等待就是这个原因。
图形显示有很多种,LCD 显示稍难,ADC 得到的结果如何在 LCD 上描点,这确实是一个难点,
for(i=0;i<128;i++) { uart_put_uchar(dot[i%30]); delay_ms(1);//此处延时当于调节了采样率
} } } 用以上调试软件同样可以看到漂亮的正弦信号图形。 以上调试成功后,是不是感觉很棒,如果你是第一次亲自完成 ADC 将数据采集,再用软件绘图 显示还原信号波形图,一定是一件特别令人激动的事情。
第 2 页,共 34 页
图 1-2 串口调试 ADC 调试 ADC 还有一种更方便的方法,结果直接在 Mini51 板上的数码管上显示出来,不管你对数 码管硬件熟悉不熟悉,只要使用模板程序提供的数码管驱动函数 led_disp(uint number)即可。 Mini51 板数码管驱动函数 led_disp(unsigned int)。 void led_disp(uint number) //Mini51 板数码管显示函数,传入整数 0~9999 {
便。有了以上 4 个函数,再建一个 keil 工程,添加一个主函数,就可以演示了。
#include "mini51b.h" //所有与硬件相关的接口函数定义
#include "uart.h"
void main()
{
rs232_port_init(); //串口初始化
read_adc();
//首个 ADC 数据丢失
0x80,0x9a,0xb4,0xcb,0xdf,0xee,0xf9,0xff,0xff,0xf9, 0xee,0xdf,0xcb,0xb4,0x9a,0x80,0x65,0x4c,0x34,0x21, 0x11,0x6,0x0,0x0,0x6, 0x10,0x20,0x34,0x4b,0x65, }; void main() { unsigned char i; rs232_port_init(); delay_ms(1); while(1) {
SEG_Q = tab1[temp]; flag = 1; } else { SEG_Q = 0xff; //数码管熄灭 flag = 0; } temp = number/100%10; //百位数码管 if(flag | temp) { SEG_B = tab1[temp]; flag = 1; } else { SEG_B = 0xff;//数码管熄灭 flag = 0; } temp = number/10%10; //十位数码管 if(flag | temp) SEG_S = tab1[temp]; else SEG_S = 0xff; //数码管熄灭 temp = number%10; //个位数码管 SEG_G = tab1[temp];
图 1-5 正弦表发生器
第 5 页,共 34 页
【量化阶数】就是 ADC 位数,例如 tlc1549 是 10 阶,ADC0809 是 8 阶; 【采样点数】就是在一个正弦周期内,均匀分布多少个采样点,例如在 128 点的 lcd 上显示 2 个以上周期的话,采样点数要小于 64 点,这里选用 30 点数来举例,源程序如下。 #include "mini51b.h" //所有与硬件相关的接口函数定义 #include "uart.h" unsigned char code dot[30]={ //正弦表,注意数据类型是“code”,存放在 rom 当中
SCON=0x50; //串口工作在方式 1,异步模式 PCON=0x80; //波特率翻倍
TMOD=0x20; //定时器 1 工作在方式 2
TH1=0xff; //波特率 115200bps,单片机时钟晶振为 22.1184MHz
TL1=0xff;
TR1 = 1; //开启时钟
RI = 0; TI = 0;
第 3 页,共 34 页
} else {
SEG_Q = 0xbf;//"-" SEG_B = 0xbf; SEG_S = 0xbf; SEG_G = 0xbf; } } 以上演示源程序 keil 工程请参考附件【串口调试 1】
这里我再介绍两款串口绘图软件【MyOsc】和【ComCalWave】,可以直接把串口接收到的数据 按 X-Y 轴绘图,显示结果更直观。
从串口读 1 字节函数 unsigned char uart_get_uchar()。
unsigned char uart_get_uchar() //从串口读 1 字节无符号数据
{
while(!RI);
RI = 0;
return SBUF;
} 以上这几个函数是学单片机的人一定要掌握的,能够随手拿来就用,通过串口调试程序,很方
涉及 LCD 驱动问题,需要花费很大篇幅才能完成。 最初调试我们可以选用串口来做,借助他人现成的工具软件。下面介绍基于串口和上位机工具
软件的波形显示程序设计。
串口初始化函数 rs232_port_init(void)。 void rs232_port_init(void) //串口初始化
{
第 1 页,共 34 页