|
首先说明:我才接触51单片机3个星期(6月8号才高考完),对C语言还很陌生。我就是一个萌新,还希望大佬们多多指导。
12864(带字库st7920驱动)为显示器,XPT2046为AD转换芯片。(不要问我为什么用这个芯片,开发板自带的坑货。我在网上下载的示波器程序大多以ADC0832或ADC0808为AD转换芯片,结果我都用不了,所以才被迫自写程序。)
示波器程序由main.c XPT2046.c XPT2046.h三个子文件构成,main.c是我根据网上的一个12864画图程序改编而成我也加了一些注释,后面两个文件取自开发板自带的例程并进行了修改。所以说这个程序基本上不是我编写的,也有很多问题和不足之处还请指正。
下面是效果图。
首先是方波。
再是正弦波。
由于没有函数发生器,就只能通过手机播放只做好的正弦音频,再检测手机耳机接口信号。
不知道为什么,正弦波有一半不见了,似乎是由于不能检测到负电压还是什么的。。。
下面贴出main.c的代码。
- #include <reg52.h>
- #include"XPT2046.h"
- #define uint unsigned int
- #define uchar unsigned char
- sbit RS=P2^6; //LCD数据或命令选择端
- sbit RW=P2^5; //LCD写入或读出选择端
- sbit RST=P1^0; //LCD复位端口
- sbit LCDE=P2^7; // LCD使能端
- sbit PSB=P3^2;//串行或并行选择端
- void delay(uchar i)
- {
- while(i--);
- } //延时函数,i=1时延时约10微秒(12M晶振)
- void SPI_Start()
- {
- CLK = 0;
- CS = 1;
- DIN = 1;
- CLK = 1;
- CS = 0;
- } //ADC芯片(XPT2046)初始化函数
- void lcd_busy()
- {
- RS=0;
- RW=1;
- P0=0XFF;
- LCDE=1;
- delay(14);
- while((P0&0x80)==0x80);
- LCDE=0;
- }//LCD12864(st7920驱动)查忙函数
- void write_com(uchar com)
- {
- lcd_busy();RS=0;
- RW=0;
- LCDE=0;
- P0=com;
- delay(9);
- LCDE=1;
- delay(9);
- LCDE=0;
- }//LCD写指令函数
- void write_num(uchar num)
- {
- lcd_busy();
- RS=1;
- RW=0;
- LCDE=0;
- P0=num;
- delay(7);
- LCDE=1;
- delay(9);
- LCDE=0;
- }//LCD写数据函数
- uchar read_data()
- {
- uchar read;
- lcd_busy();
- RS=1;
- RW=1;
- LCDE=0;
- delay(7);
- LCDE=1;
- delay(9);
- read=P0;
- LCDE=0;
- delay(11);;
-
- return read;
- } //LCD读数据函数
- void clear_lcd()
- {
- uchar i,j;
- write_com(0x34);
- for(i=0;i<32;i++) //因为LCD有纵坐标32格所以写三十二次
- {
- write_com(0x80+i); //先写入纵坐标Y的值
- write_com(0x80); //再写入横坐标X的值
- for(j=0;j<32;j++) //横坐标有16位,每位写入两个字节的的数据,也就写入32次
- { //因为当写入两个字节之后横坐标会自动加1,所以就不用再次写入地址了。
- write_num(0x00);
- }
- }
- write_com(0x36);
- write_com(0x30);
- } //LCD清屏函数
- void put_point(uchar x,uchar y)
- {
- uint bt=0,read=0;
- uchar x_adr,y_adr,h_bit,l_bit;
- y_adr=0x80+y%32; //计算Y轴的地址,应为纵坐标有64个,所有对32求余,当Y大于31时,Y的坐标是下半屏的。
- if(y>31) //计算X轴的地址当Y大于31时X的地址在下半屏,从0X88开始,小于31时X的地址是在上半屏,从0X80开始
- x_adr=0x88+x/16;
- else
- x_adr=0x80+x/16;
- bt=0x8000>>(x%16); //求这个点到底是在哪个点
- write_com(0x34);
- write_com(0x34);
- write_com(y_adr); //读取数据的时候要先写入所取数据的地址
- write_com(x_adr);
- read_data(); //读取的第一个字节不要,
- read=read_data(); //从第二个字节开始接收。
- read<<=8;
- read|=read_data();
- bt=bt|read;
- h_bit=bt>>8;
- l_bit=bt;
- write_com(y_adr); //写入点的时候,重新写入地址,因为地址已经改变。
- write_com(x_adr);
- write_num(h_bit);
- write_num(l_bit);
- write_com(0x36); //开显示
- write_com(0x30); //转回基本指令集
- }//LCD画点函数
- /*
- 液晶初始化
- */
- void lcd_init()
- {
- PSB=1;
- RST=1;
- write_com(0x30); //基本指令操作
- write_com(0x0c); //开显示
- write_com(0x01); //清除LCD显示
- }
- void main()
- {
-
- float i;
- uchar x,n,y;
- lcd_init();
- clear_lcd();
- while(1)
- {
- SPI_Start();
- write_com(0x34);
- write_com(0x34);
- write_com(0x80);
- write_com(0x88);
- for(i=16;i>0;i--) //画出X轴
- {
- write_num(0xff);
- }
- for(i=0;i<64;i++) //画出Y轴
- {
- put_point(0,i);
- }
- for(i=0;i<128;i++)
- {
- x=i;//使横坐标自动向前移
- n = Read_AD_Data(0xE4);//接收返回的AD值
- y=32-(n/10);//确定点的纵坐标(纵坐标是AD值,不是电压。)
- put_point(x,y);
- delay(100);
- }
- write_com(0x36);
- write_com(0x30);
- while(1);
- }
-
- }//主函数
复制代码
全部资料下载地址:
示波器(自制).zip
(38.06 KB, 下载次数: 238)
|
评分
-
查看全部评分
|