51单片机驱动ADC0832模数转换程序lcd1602显示
- 格式:docx
- 大小:18.55 KB
- 文档页数:6
51单片机驱动1602液晶显示器c程序/*程序效果:单片机控制液晶显示器1602 显示字母数字,用户自行更改io程序原创安全:51hei*/#includereg52.h //头文件#define uchar unsigned char //宏定义#define uint unsigned intuchar code table[]=“51HEI XING XING “ ; //显示的字母uchar code table1[]=“51HEI MCUXUE YUAU” ;sbit lcdrs=P1; //寄存器选择引脚sbit lcdwr=P1;//读写引脚sbit lcde=P1 ; //片选引脚void delay(uchar x) //延时子函数{uchar i,j;for(i=x;i0;i--) for(j=110;j0;j--);}void write_com(uchar com) //写指令子函数{ //根据1602 液晶显示器协议编写P2=com; lcdrs=0;lcdwr=0;delay(5);lcde=0; delay(5);lcde=1; }void write_dat(uchar dat) //写数据子函数{P2=dat; lcdrs=1;lcdwr=0;delay(5);lcde=0;delay(5);lcde=1;}void init() //初始化子函数{write_com(0x01); //清屏write_com(0x3f); //功能设置write_com(0x0d); //显示控制write_com(0x06); //输入方式设置}void main(){ uchar i; //定义局部变量init();write_com(0x80+0x02+0x10); //指针的位置for(i=0;i15;i++) //显示{ write_dat(table[i]); delay(50); //延时,用于调节速度不匹配}write_com(0x80+0x40+0x10);for(i=0;i16;i++){ write_dat(table1[i]); delay(50);}for(i=0;i16;i++){ write_com(0x18); delay(50);} while(1);}tips:感谢大家的阅读,本文由我司收集整编。
显示频率,幅度可调,可产生四种波形,正弦波,方波,锯齿波,三角波,希望你能喜欢,给你发了一张效果图,喜欢的话别忘了采纳我的回答啊#include<reg52.h>#define uchar unsigned char#define uint unsigned int#define DAdata P0 //DA数据端口sbit DA_S1= P2^0; // 控制DAC0832的8位输入寄存器,仅当都为0时,可以输出数据(处于直通状态),否则,输出将被锁存sbit DA_S2= P2^1; // 控制DAC0832的8位DAC寄存器,仅当都为0时,可以输出数据(处于直通状态),否则,输出将被锁存sbit key= P3^2;uchar wavecount; //'抽点'计数uchar THtemp,TLtemp;//传递频率的中间变量uchar judge=1; //在方波输出函数中用于简单判别作用uchar waveform; //当其为0、1、2时,分别代表三种波uchar code freq_unit[3]={10,50,200}; //三种波的频率单位uchar idata wavefreq[3]={1,1,1}; //给每种波定义一个数组单元,用于存放单位频率的个数uchar code lcd_hang1[]={"Sine Wave " "Triangle Wave " "Square Wave " "Select Wave: " "press No.1 key! "};uchar idata lcd_hang2[16]={"f= Hz "};uchar code waveTH[]={0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xec,0xf6,0xf9,0xfb,0xfc,0xfc,0xfd,0xfd,0xfd,0xfe};uchar code waveTL[]={0x06,0x8a,0x10,0x4e,0x78,0x93,0xa8,0xb3,0xbe,0xc6, //正弦波频率调整中间值0xac,0xde,0x48,0x7a,0x99,0xaf,0xbb,0xc8,0xd0,0xde, //三角波频率调整中间值0x88,0x50,0x90,0x32,0x34,0xbe,0x4a,0xa3,0xe5,0x2c};/**************************************************************************************** *********/uchar code triangle_tab[]={ //每隔数字8,采取一次0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38,0x40,0x48,0x50,0x58,0x 60,0x68,0x70,0x78,0x80,0x88,0x90,0x98,0xa0,0xa8,0xb0,0xb8,0xc0,0xc8,0xd0,0xd8,0x e0,0xe8,0xf0,0xf8,0xff,0xf8,0xf0,0xe8,0xe0,0xd8,0xd0,0xc8,0xc0,0xb8,0xb0,0xa8,0xa0,0x9 8,0x90,0x88,0x80,0x78,0x70,0x68,0x60,0x58,0x50,0x48,0x40,0x38,0x30,0x28,0x20,0x 18,0x10,0x08,0x00};uchar code sine_tab[256]={//输出电压从0到最大值(正弦波1/4部分)0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,0x99,0x9c,0x9f,0xa2,0xa 5,0xa8,0xab,0xae,0xb1,0xb4,0xb7,0xba,0xbc,0xbf,0xc2,0xc5,0xc7,0xca,0xcc,0xcf,0xd1,0xd4,0xd6,0xd8,0xda,0xdd ,0xdf,0xe1,0xe3,0xe5,0xe7,0xe9,0xea,0xec,0xee,0xef,0xf1,0xf2,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd, 0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,//输出电压从最大值到0(正弦波1/4部分)0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7 ,0xf6,0xf5,0xf4,0xf2,0xf1,0xef,0xee,0xec,0xea,0xe9,0xe7,0xe5,0xe3,0xe1,0xde,0xdd,0xda,0xd8,0x d6,0xd4,0xd1,0xcf,0xcc,0xca,0xc7,0xc5,0xc2,0xbf,0xbc,0xba,0xb7,0xb4,0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9 c,0x99 ,0x96,0x93,0x90,0x8d,0x89,0x86,0x83,0x80,//输出电压从0到最小值(正弦波1/4部分)0x80,0x7c,0x79,0x76,0x72,0x6f,0x6c,0x69,0x66,0x63,0x60,0x5d,0x5 a,0x57,0x55,0x51,0x4e,0x4c,0x48,0x45,0x43,0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,0x2e,0x2b,0x29,0x27,0x25,0x 22,0x20,0x1e,0x1c,0x1a,0x18,0x16 ,0x15,0x13,0x11,0x10,0x0e,0x0d,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x 03,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,//输出电压从最小值到0(正弦波1/4部分)0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02 ,0x02,0x03,0x04,0x05,0x 06,0x07,0x08,0x09,0x0a,0x0b,0x0d,0x0e,0x10,0x11,0x13,0x15 ,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x 29,0x2b,0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d,0x40,0x43,0x45,0x48,0x4c,0x4e,0x51,0x55,0x57,0x5a,0x5d,0x60,0x 63,0x66 ,0x69,0x6c,0x6f,0x72,0x76,0x79,0x7c,0x80};void delay(uchar z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void triangle_out() //三角波输出{DAdata=triangle_tab[wavecount++];if(wavecount>64) wavecount=0;DA_S1=0; //打开8位输入寄存器DA_S1=1; //关闭8位输入寄存器void sine_out() //正弦波输出{DAdata=sine_tab[wavecount++];DA_S1=0; //打开8位输入寄存器DA_S1=1; //关闭8位输入寄存器}void square_out() //方波输出{judge=~judge;if(judge==1) DAdata=0xff;else DAdata=0x00;DA_S1=0; //打开8位输入寄存器DA_S1=1; //关闭8位输入寄存器}/************1602液晶的相关函数*************/#define lcd_ports P1sbit rs=P2^2;sbit rw=P2^3;sbit lcden=P2^4;void write_com(uchar com){rs=0; //置零,表示写指令lcden=0;lcd_ports=com;delay(5);lcden=1;delay(5);lcden=0;}void write_date(uchar date){rs=1; //置1,表示写数据(在指令所指的地方写数据)lcden=0;lcd_ports=date;delay(5);lcden=1;delay(5);lcden=0;void disp_lcd(uchar addr,uchar *temp1){uchar num;write_com(addr);delay(1); //延时一会儿???for(num=0;num<16;num++){write_date(temp1[num]);//或者这样写write_date(*(temp1+num));delay(1);}}void init_lcd(){//uchar num;lcden=0; //可有可无???rw=0; //初始化一定要设置为零,表示写数据write_com(0x38); //使液晶显示点阵,为下面做准备write_com(0x0c); //初始设置write_com(0x06); //初始设置write_com(0x01); //清零write_com(0x80); //使指针指向第一行第一格disp_lcd(0x80,&lcd_hang1[3*16]); //在第一行显示disp_lcd(0xc0,&lcd_hang1[4*16]); //在第二行显示}/********************1602液晶函数声明结束*********************/ void main(){uchar i=0;DA_S2=0; //使DAC寄存器处于直通状态DAdata=0;DA_S1=1; //关闭8位输入寄存器init_lcd();waveform=0;TMOD=0x01; //设置定时器0为16位工作方式IT0=1; //设置外部中断0为下降沿触发ET0=1; //开定时器中断EX0=1;EA=1;while(1){//DAout(0xff); //可输出TTL波形//DAout(0x80);//T_temp=32;}}void timer0() interrupt 1{TH0=THtemp;TL0=TLtemp;if(waveform==0) sine_out();else if(waveform==1) triangle_out();else if(waveform==2) square_out();}void key_int0() interrupt 0{uchar keytemp;uint total_freq; //总频率EA=0; TR0=0; //关总中断与定时器delay(5); //延时够吗???if(key==0) //确实有按键按下而引发中断{keytemp=P3&0xf0; //获取P3口高四位的值switch(keytemp){case 0xe0: //选择波形waveform++;if(waveform>2) waveform=0;break;case 0xd0: //频率按规定单位依次增加wavefreq[waveform]++;if(wavefreq[waveform]>10) wavefreq[waveform]=1; // /*这边要用“>10”,因为它比“=11”可靠break;case 0xb0: //频率按规定单位依次衰减wavefreq[waveform]--;if(wavefreq[waveform]<1) wavefreq[waveform]=10; //这边要用“<1”,因为它比“=0”可靠性更高break;case 0x70: //TTL输出DA_S2=1; //使DAC寄存器关闭break;}THtemp=waveTH[waveform*10+(wavefreq[waveform]-1)]; //方括号中选取第几个数后,并把该值赋给T_tempTLtemp=waveTL[waveform*10+(wavefreq[waveform]-1)];total_freq= wavefreq[waveform] * freq_unit[waveform]; //求输出频率(个数*单位)lcd_hang2[5]=total_freq%10+0x30; //在液晶中显示个位,(0x30 在液晶显示中表示数字0)total_freq/=10; lcd_hang2[4]=total_freq%10+0x30; //在液晶中显示时十位total_freq/=10; lcd_hang2[3]=total_freq%10+0x30; //在液晶中显示时百位total_freq/=10; lcd_hang2[2]=total_freq%10+0x30; //在液晶中显示时千位disp_lcd(0x80,&lcd_hang1[waveform*16]); //在第一行显示disp_lcd(0xc0,lcd_hang2); //在第二行显示}wavecount=0; //'抽点'计数清零while(!key);EA=1; TR0=1; //开启总中断与定时器}。
LCD显示电路#include<reg51.h>sbit RS=P3^7; //寄存器选择位,将RS位定义为P2.0引脚sbit RW=P3^6; //读写选择位,将RW位定义为P2.1引脚sbit E=P2^7; //使能信号位,将E位定义为P2.2引脚sbit BF=P0^7; //忙碌标志位,将BF位定义为P0.7引脚#define Lcd_Data P0#include <string.h>#include<intrins.h> //包含_nop_()函数定义的头文件unsigned char code string1[ ]={0x77,0x75,0x20,0x79,0x61,0x6E,0x67,0x20,0x79,0x61,0x6E,0x67,0x20,0x20,0x20,0x20}; //第一行显示的字符void Lcd_delay1ms() // 函数功能:延时1ms//注:不同单片机不同晶振需要对此函数进行修改{ unsigned char i,j;for(i=0;i<90;i++)for(j=0;j<33;j++);}void Lcd_delay(unsigned int n) // 函数功能:延时若干毫秒,入口参数:n{ unsigned int i;for(i=0;i<n;i++)Lcd_delay1ms();}/*****************************************************函数功能:判断液晶模块的忙碌状态返回值:result。
result=1,忙碌;result=0,不忙***************************************************/bit Lcd_BusyTest(void)bit result;RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态RW=1;E=1; //E=1,才允许读写_nop_(); //空操作_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间result=BF; //将忙碌标志电平赋给resultE=0;return result;}/*****************************************************函数功能:将模式设置指令或显示地址写入液晶模块入口参数:dictate***************************************************/void Lcd_WriteCom (unsigned char dictate){ while(Lcd_BusyTest()==1); //如果忙就等待RS=0; //根据规定,RS和R/W同时为低电平时,可以写入指令RW=0;E=0; //E置低电平(写指令时就是让E从0到1发生正跳变,所以应先置ぜ? _nop_();_nop_(); //空操作两个机器周期,给硬件反应时间Lcd_Data=dictate; //将数据送入P0口,即写入指令或地址_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}/*****************************************************函数功能:指定字符显示的实际地址x入口参数:注:此函数已经加上了0x80,故只需写上实际地址就行***************************************************/void Lcd_WriteAddress(unsigned char x){ Lcd_WriteCom(x|0x80); //显示位置的确定方法规定为80H+地址码x/*****************************************************函数功能:将数据(字符的标准ASCII码)写入液晶模块入口参数:y(为字符常量)***************************************************/void Lcd_WriteData(unsigned char y){while(Lcd_BusyTest()==1);RS=1; //RS为高电平,RW为低电平时,可以写入数据RW=0;E=0; //E置低电平(写指令时就是让E从0到1发生正跳变所以应先置ぜ?Lcd_Data=y; //将数据送入P0口,即将数据写入液晶模块_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=1; //E置高电平_nop_();_nop_();_nop_();_nop_(); //空操作四个机器周期,给硬件反应时间E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令}/*****************************************************函数功能:对LCD的显示模式进行初始化设置***************************************************/void Lcd_Int(void){Lcd_delay(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间Lcd_WriteCom(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口Lcd_delay(5); //延时5msLcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);设置模式次写9// Lcd_WriteCom(0x38);Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x38); //9次写设置模式Lcd_delay(5);Lcd_WriteCom(0x0C); //显示模式设置:显示开,有光标,光标闪烁Lcd_delay(5);Lcd_WriteCom(0x06); //显示模式设置:光标右移,字符不移Lcd_delay(5);Lcd_WriteCom(0x01); //清屏幕指令,将以前的显示内容清零Lcd_delay(5); }void hanying_show(void){unsigned char Lcd_i;Lcd_WriteCom(0x01);//清显示:清屏幕指令Lcd_delay(2);Lcd_WriteAddress(0x00); // 设置显示位置为最左侧Lcd_delay(2);Lcd_i=0;while(string1[Lcd_i]!='\0') //'\0'是数组结束标志需先将字符存入{Lcd_WriteData(string1[Lcd_i]); // 显示字符Lcd_i++;Lcd_delay(4);}}void main(){Lcd_Int(); //1602初始化while(1){hanying_show();}}。
//********************************//说明:调用VR2时,ADC0832将模拟电压转换为数字电压并显示在LCD1602上//********************************#include<reg51.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define delay4us(){_nop_();_nop_();_nop_();_nop_();}//********************************//ADC引脚定义//********************************sbit CS=P3^0;sbit CLK=P3^1;sbit DIO=P3^2;//********************************//LCD端口定义//********************************sbit RS=P2^0;sbit RW=P2^1;sbit E=P2^2;//********************************//一位整数、两位小数的数字电压显示缓冲//********************************uchar Display_Buffer[]="0.000V";//********************************//LCD第一行显示信息//********************************uchar code Line[]="TEST OK DC ";//********************************//延时子程序//********************************void DelayMS(uint x){uchar t;while(x--)for(t=0;t<120;t++);}//********************************//LCD忙状态检测//********************************bit LCD_BUSY_CHECK(){bit result;RS=0;RW=1;E=1;delay4us();result=(bit)(P0&0x80);E=0;return result;}//********************************//写LCD命令//********************************void LCD_Write_Command(uchar cmd){while(LCD_BUSY_CHECK()); //判断LCD是否忙碌RS=0;RW=0;E=0;_nop_();P0=cmd;delay4us();E=1;delay4us();E=0;}//********************************//设置LCD显示位置//********************************void Set_Disp_Pos(uchar pos){LCD_Write_Command(pos|0x80);}//********************************//写LCD数据//********************************void LCD_Write_Data(uchar dat){while(LCD_BUSY_CHECK()); //判断LCD是否忙碌RS=1;RW=0;E=0;P0=dat;delay4us();E=1;delay4us();E=0;}//********************************//LCD初始化//********************************void LCD_Initialise(){LCD_Write_Command(0x38);DelayMS(1);LCD_Write_Command(0x0C);DelayMS(1);LCD_Write_Command(0x06);DelayMS(1);LCD_Write_Command(0x01);DelayMS(1);}//********************************//获取AD转换结果(0通道)//********************************uchar GET_AD_RESULT(){uchar i;uchar dat1=0;uchar dat2=0;//起始控制位CS=0;CLK=0;DIO=1;_nop_(); _nop_();CLK=1;_nop_(); _nop_();//第一个下降沿之前,社DI=1/0//选择单端/差分(SGL\DIF)模式中的单端输入模式CLK=0;DIO=1;_nop_(); _nop_();CLK=1;_nop_(); _nop_();//第二个下降沿之前,设DI=0/1,选择CH0\CH1CLK=0;DIO=0;_nop_(); _nop_();CLK=1;DIO=1;_nop_(); _nop_();//第三个下降沿之前,设DI=1CLK=0;DIO=1;_nop_(); _nop_();//第四个至第十一个,共八个下降沿读数据(MSB_LSB) for(i=0;i<8;i++){CLK=1;_nop_(); _nop_();CLK=0;_nop_(); _nop_();dat1=dat1<<1|DIO;}//第十一个至第十八个,共八个下降沿读数据(LSB_MSB) for(i=0;i<8;i++){dat2=dat2|((uchar)(DIO)<<i);CLK=1;_nop_(); _nop_();CLK=0;_nop_(); _nop_();}CS=1;//如果MSB_LSB和LSB_MSB读取的结果相同,则返回读取的结果,否则返回0 return(dat1==dat2)?dat2:0;}//***************************//主函数//***************************void main(){uchar i;uint d;uint c;LCD_Initialise();DelayMS(10);while(1){//获取AD转换值,最大值为255对应于最高电压5.00V//本例中设计为三个显示数位,故用500d=GET_AD_RESULT()*5000.0/255;//将AD转换后的数据分解为3个数位Display_Buffer[0]=d/1000+'0';Display_Buffer[2]=d%1000/100+'0';Display_Buffer[3]=d%100/10+'0';Display_Buffer[4]=d%10+'0';Set_Disp_Pos(0x00);i=0;while(Line[i]!='\0')LCD_Write_Data(Line[i++]);Set_Disp_Pos(0x46);i=0;while(Display_Buffer[i]!='\0')LCD_Write_Data(Display_Buffer[i++]);}}。
#include<reg52.h>#include<intrins.h>//为了使用这个头文件中的_nop_()延时函数sbit sda=P2^0;//SDA线sbit scl=P2^1;//SCL线sbit rst=P2^4; //关掉时钟芯片输出sbit hc573_sg_le=P2^6; //对用于锁存段数据的573锁存LE端进行定义sbit hc573_bit_le=P2^7;//对用于锁存位选通数据的573锁存LE端进行定义sbit lcd_rs=P1^0; //1602数据/命令选择端,高电平执行数据操作,低电平执行命令操作sbit lcd_rw=P1^1;//1602读/写控制端高电平读,低电平写sbit lcd_en=P2^5;//1602读写控制使能信号,它为高脉冲信号才可执行读写操作sbit sta7=P0^7;//1602忙信号检测位,为1则忙,需等待,为0表示空闲void delay_ms(unsigned int t) //tms的延时函数{unsigned int a,b;for(a=0;a<t;a++){for(b=0;b<113;b++){;}}}void _nop5_()//5个机器周期的延时,大约延时5us{_nop_();_nop_();_nop_();_nop_();_nop_();}void iic_start()//主机发送开始信号的函数{scl=0;//SCL线拉低,以便让SDA线准备变化sda=1;//SDA线拉高,准备产生开始信号scl=1;//SCL线拉高_nop5_(); //SDA线高电平持续5us,以符合开始信号定义的要求(>4.7us)sda=0;//SDA线拉低,产生开始信号_nop5_();//SDA线低电平持续5us,以符合开始信号定义的要求(>4us)}void iic_stop()//主机发送停止信号的函数{scl=0;//SCL线拉低,以便让SDA线准备变化sda=0;//SDA线拉低,准备产生停止信号scl=1;//SCL线拉高_nop5_(); //SDA线低电平持续5us,以符合停止信号定义的要求(>4us)sda=1;//SDA线拉高,产生停止信号_nop5_(); //SDA线的高电平持续5us,以符合停止信号定义的要求(>4.7us)}void iic_ack()//检测从机应答信号的函数{unsigned char i;i=255;scl=0;//SCL线拉低,以便让SDA线准备变化sda=1;//SDA线拉高,准备检测从机的应答信号while(sda==1)//当SDA为高电平时,则等待从机的应答将SDA拉低{if(i>0)i--;else return; //如果i自减到0了,从机还没响应,则不再等待,返回}//这种情况极少发生,一般是从机器件出问题了才会发生scl=1;//从机已经应答,将SDA线拉低了_nop5_();//SDA线的低电平持续5us,以符合应答信号定义的要求(>4us)scl=0;//SCL线拉低,以便让从机把SDA线释放}void send_ack()//主机给从机发送应答信号{scl=0;//SCL线拉低,以便让SDA线准备变化sda=0;//SDA线拉低,即将发送应答信号给从机scl=1;//SCL线拉高,将应答信号发送过去_nop5_();//SDA线的低电平持续5us,以符合应答信号定义的要求(>4us)scl=0;//SCL线拉低,以便让SDA线准备变化sda=1;//释放SDA线}void iic_send_no_ack()//主机给从机发送非应答信号{scl=0;//SCL线拉低,以便让SDA线准备变化sda=1;//SDA线拉高,即将发送非应答信号给从机scl=1;//SCL线拉高,将应答信号发送过去_nop5_();//SDA线的高电平持续5us,以符合非应答信号定义的要求(>4us)}void iic_write(unsigned char dat)//主机向从机写操作函数{unsigned char i;for(i=0;i<8;i++){scl=0;//SCL线拉低,以便让SDA线准备变化sda=(bit)(0x80&dat); //取字节数据的最高位,发送到SDA线dat=dat<<1;//发送的数据都是由高位到低位顺序发送的,所以要将所//需发送的那位移到数据的最高位,以发送到SDA线上scl=1;//SCL线拉高,数据被发送过去}}unsigned char iic_read()//主机向从机读操作的函数{unsigned char i;unsigned char dat; //定义一个字节变量,用来存储读出的从机数据dat=0;for(i=0;i<8;i++){dat=dat<<1;//将位数据不断地往高位移动,将接收到的位数据转换为字节数据scl=0;//SCL线拉低,以便让SDA线准备变化dat=dat|(unsigned char)sda;//将接收到的位数据强制转换成字节数据,并存到dat 中scl=1;//SCL线拉高,接收下一位数据}return dat;//数据接收完毕,带数据返回}void lcd_busy_check(void)//1602忙信号检测,忙则等待{P0=0xff;do{lcd_rs=0;//读状态操作,为0lcd_rw=1;//读操作为1lcd_en=0;lcd_en=1;//读状态,需为高电平}while (sta7==1);//如果为1则忙,等待...直到为0lcd_en=0;}void lcd_write_cmd(unsigned char cmd) //液晶写命令函数{lcd_busy_check(); //每次操作之前都要进行忙信号检测lcd_rs=0;//执行命令操作,为0lcd_rw=0;//写操作,为0P0=cmd;//送指令到液晶数据端口P0,准备执行命令_nop_();//这是一个延时函数,可延时一个机器周期,它在“intrins.h”中lcd_en=1;//高电平,指令送入液晶控制器_nop_();//保持一会儿,使指令可靠地送入液晶控制器lcd_en=0;//低电平,执行命令}void lcd_write_data(unsigned char dat) //液晶写数据函数{lcd_busy_check();//每次操作之前都要进行忙信号检测lcd_rs=1;//执行数据操作,为1lcd_rw=0;//写操作,为0P0=dat;//送数据到液晶数据端口P0,准备执行数据操作_nop_();lcd_en=1;//高电平,数据送入液晶液晶数据RAM_nop_();//保持一会儿,使显示数据可靠地送入液晶数据RAMlcd_en=0;//低电平,显示数据}void lcd1602_init()//液晶显示初始化操作{P0=0x00;hc573_sg_le=0;//关闭HC573使数码管不显示hc573_bit_le=0;lcd_en=0;//为0,为实现高脉冲作准备lcd_write_cmd(0x38);//设置为5x7显示lcd_write_cmd(0x0c);// 打开显示-显示光标-光标闪烁lcd_write_cmd(0x6);//地址加一,光标右移,整屏显示不移动lcd_write_cmd(0x01);//清屏}/*--这个函数的作用是:将读到的8591中的数据换算为电压值的个位值,----并转换为对应的ASCII码,用以在液晶中显示*/unsigned char data1_convert(unsigned char dat_temp){unsigned char data1;data1=(unsigned char)(((float)dat_temp/255)*5); //换算为电压值的个位值data1=data1+48; //转换为对应的ASCII码,因为0对应ASCII码的48,以此类推return data1;}/*--这个函数的作用是:将读到的8591中的数据换算为电压值的小数点后第一位的值,----并转换为对应的ASCII码,用以以在液晶中显示*/unsigned char data0_convert(unsigned char dat_temp){unsigned char data0,data1;data1=(unsigned char)(((float)dat_temp/255)*5);//换算为电压值的个位值data0=(unsigned char)((((float)dat_temp/255)*5-data1)*10);//换算为为电压值的小--//--数点后第一位的那个值data0=data0+48;return data0;//转换为对应的ASCII码}void main(){unsigned char dat;//用于接收从8591中读到的数据lcd1602_init();rst=0;//关闭DS1302时钟芯片,避免引起干扰hc573_sg_le=0;hc573_bit_le=0;lcd_write_cmd(0x80);lcd_write_data('C');lcd_write_data('H');lcd_write_data('1');lcd_write_data(':');lcd_write_cmd(0x85);lcd_write_data('.');lcd_write_cmd(0x87);lcd_write_data('V');//上面的这些都是为了在1602中显示"CH1: : V"while(1){iic_start();iic_write(0x90);//对8591进行写操作iic_ack();iic_write(0x01);//设置为4路独立信号输入,并关闭通道自动加1,只用通道1iic_ack();iic_start();//重新开始,为读数据作准备iic_ack();iic_write(0x91);//对8591进行读操作iic_ack();dat=iic_read();//这还只是一个8位的数据(需进一步转换为实际电压值)iic_send_no_ack();iic_stop();lcd_write_cmd(0x84); //将要显示的字符显示在此地址处lcd_write_data(data1_convert(dat));//显示电压的整数部分lcd_write_cmd(0x86);//将要显示的字符显示在此地址处lcd_write_data(data0_convert(dat)); //显示电压的小数部分}}。
基于51单⽚机控制LCD1602液晶屏显⽰LCD1602⼀共有16个接⼝,其中RS,RW,EN,D0,D1,D2,D3,D4,D5,D6,D7⽤于读写数据也就是说是并⾏通信。
判断液晶忙:判断STA7是否为1,所以将P0⼝总线的数据和0x80(1000 0000)进⾏与运算。
每次对1602写指令都需要判断是否忙。
void Read_busy(){uchar busy;P0 = 0xff;RS = 0;RW = 1;do{EN = 1;busy = P0;EN = 0;}while(busy & 0x80);}写字节和写数据都是按照1602的数据⼿册来写的。
写LCD1602命令⼀个字节:void Write_Cmd(uchar cmd){Read_busy();RS = 0;RW = 0;P0 = cmd;EN = 1;EN = 0;}写⼀个字节数据:void Write_Dat(uchar dat){Read_busy();RS = 1;RW = 0;P0 = dat;EN = 1;EN = 0;}由上⾯的函数,就可以初始化LCD1602。
1602初始化函数:void Init_LCD1602(){LCD1602_Write_Cmd(0x38); //设置16*2显⽰,5*7点阵,8位数据接⼝LCD1602_Write_Cmd(0x0c); //开显⽰,不显⽰光标(0xf开显⽰,显⽰光标,光标闪烁)LCD1602_Write_Cmd(0x01); //清除显⽰LCD1602_Write_Cmd(0x06); //读写⼀字节后地址指针加1 Write_Cmd(0x80 | 0x00); //设置显⽰地址(显⽰在第⼀⾏第⼀个)设置显⽰地址以及设置读写地址指针⽅向⼀定要在清除显⽰之后要不然仍会显⽰在第⼀个格)LCD1602RAM在显⽰数字的时候要⽤ Write_Dat(3 + '0');显⽰字母使⽤ASCLL码(例如:显⽰H:Write_Dat(0x48);)在指定位置显⽰⼀个字符:要显⽰的横坐标取值0-40要显⽰的⾏坐标取值0-1(0为第⼀⾏,1为第⼆⾏)dat:需要显⽰的数据以ASCLL形式显⽰void LCD1602_Dis_OneChar(uchar x, uchar y,uchar dat){if(y) x |= 0x40;x |= 0x80;LCD1602_Write_Cmd(x);LCD1602_Write_Dat(dat);}显⽰字符串的时候就需要⽤到指针:在指定位置显⽰字符串:要显⽰的横坐标取值0-40要显⽰的⾏坐标取值0-1(0为第⼀⾏,1为第⼆⾏)*str:需要显⽰的字符串void LCD1602_Dis_Str(uchar x, uchar y, uchar *str){if(y) x |= 0x40;x |= 0x80;LCD1602_Write_Cmd(x);while(*str != '\0'){LCD1602_Write_Dat(*str++);}}调⽤⽅式:uchar TestStr[] = {"Welcome!"};LCD1602_Dis_Str(0, 0, &TestStr[0]);显⽰简单的数字:#include <reg52.h>#define uchar unsigned char#define uint unsigned intsbit RS = P3^5;sbit RW = P3^6;sbit EN = P3^4;void Read_busy() //判断液晶忙{uchar busy;P0 = 0xff;RS = 0;RW = 1;do{EN = 1;busy = P0;EN = 0;}while(busy & 0x80);}void Write_Cmd(uchar cmd) //写LCD1602命令⼀个字节{Read_busy();RS = 0;RW = 0;P0 = cmd;EN = 1;EN = 0;}void Write_Dat(uchar dat) //写⼀个字节数据{Read_busy();RS = 1;RW = 0;P0 = dat;EN = 1;EN = 0;}void main(){Write_Cmd(0x38);//设置16*2显⽰Write_Cmd(0x0f);//开显⽰显⽰光标,光标闪烁Write_Cmd(0x01);//清屏Write_Cmd(0x06);//地址指针移位命令Write_Cmd(0x80 | 0x00);//显⽰地址Write_Dat(1 + '0');Write_Dat(2 + '0');Write_Dat(3 + '0');Write_Dat(4 + '0');Write_Dat(5 + '0');while(1);}显⽰字符串:#include <reg52.h>typedef unsigned char uchar;typedef unsigned int uint;#define LCD1602_DB P0 //LCD1602数据总线sbit LCD1602_RS = P3^5; //RS端sbit LCD1602_RW = P3^6; //RW端sbit LCD1602_EN = P3^4; //EN端sbit DU = P2^6;//sbit WE = P2^7;//数码管位选段选⽤于关闭数码管显⽰/*=================================================*函数名称:Read_Busy*函数功能:判断1602液晶忙,并等待=================================================*/void Read_Busy(){uchar busy;LCD1602_DB = 0xff;//复位数据总线LCD1602_RS = 0; //拉低RSLCD1602_RW = 1; //拉⾼RW读do{LCD1602_EN = 1;//使能ENbusy = LCD1602_DB;//读回数据LCD1602_EN = 0; //拉低使能以便于下⼀次产⽣上升沿}while(busy & 0x80); //判断状态字BIT7位是否为1,为1则表⽰忙,程序等待}/*=================================================*函数名称:LCD1602_Write_Cmd*函数功能:写LCD1602命令*调⽤:Read_Busy();*输⼊:cmd:要写的命令=================================================*/void LCD1602_Write_Cmd(uchar cmd){Read_Busy(); //判断忙,忙则等待LCD1602_RS = 0;LCD1602_RW = 0; //拉低RS、RW操作时序情况1602课件下中⽂使⽤说明基本操作时序章节 LCD1602_DB = cmd;//写⼊命令LCD1602_EN = 1; //拉⾼使能端数据被传输到LCD1602内LCD1602_EN = 0; //拉低使能以便于下⼀次产⽣上升沿}/*=================================================*函数名称:LCD1602_Write_Dat*函数功能:写LCD1602数据*调⽤:Read_Busy();*输⼊:dat:需要写⼊的数据=================================================*/void LCD1602_Write_Dat(uchar dat){Read_Busy();LCD1602_RS = 1;LCD1602_RW = 0;LCD1602_DB = dat;LCD1602_EN = 1;LCD1602_EN = 0;}/*=================================================*函数名称:LCD1602_Dis_OneChar*函数功能:在指定位置显⽰⼀个字符*调⽤:LCD1602_Write_Cmd(); LCD1602_Write_Dat();*输⼊:x:要显⽰的横坐标取值0-40,y:要显⽰的⾏坐标取值0-1(0为第⼀⾏,1为第⼆⾏)dat:需要显⽰的数据以ASCLL形式显⽰=================================================*/void LCD1602_Dis_OneChar(uchar x, uchar y,uchar dat){if(y) x |= 0x40;x |= 0x80;LCD1602_Write_Cmd(x);LCD1602_Write_Dat(dat);}/*=================================================*函数名称:LCD1602_Dis_Str*函数功能:在指定位置显⽰字符串*调⽤:LCD1602_Write_Cmd(); LCD1602_Write_Dat();*输⼊:x:要显⽰的横坐标取值0-40,y:要显⽰的⾏坐标取值0-1(0为第⼀⾏,1为第⼆⾏)*str:需要显⽰的字符串=================================================*/void LCD1602_Dis_Str(uchar x, uchar y, uchar *str){if(y) x |= 0x40;x |= 0x80;LCD1602_Write_Cmd(x);while(*str != '\0'){LCD1602_Write_Dat(*str++);}}/*=================================================*函数名称:Init_LCD1602*函数功能:1602初始化*调⽤: LCD1602_Write_Cmd();=================================================*/void Init_LCD1602(){LCD1602_Write_Cmd(0x38); // 设置16*2显⽰,5*7点阵,8位数据接⼝ LCD1602_Write_Cmd(0x0c); //开显⽰LCD1602_Write_Cmd(0x06); //读写⼀字节后地址指针加1LCD1602_Write_Cmd(0x01); //清除显⽰}void main(){uchar TestStr[] = {"Welcome!"};DU = 0;WE = 0;//关闭数码管显⽰Init_LCD1602();//1602初始化LCD1602_Dis_Str(0, 0, &TestStr[0]); //显⽰字符串LCD1602_Dis_OneChar(10, 1, 0xff); //显⽰⼀个⿊⽅格while(1);}。
ADC0832双通道1602显示/********************************************************//*杭州电子&计算机工作室 *//*/doc/011497542.html, *//*ADC0832测试程序 *//*目标器件:AT89S51 *//*晶振:11.0592MHZ *//*编译环境:Keil 7.50A *//********************************************************//*********************************包含头文件********************************/#include#include#define uint unsigned int#define uchar unsigned char#define yh 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)#define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)/*********************************端口定义**********************************/sbit ADCS = P1^2;sbit ADCLK = P1^0;sbit ADDIO = P1^1;//液晶屏的与C51之间的引脚连接定义(显示数据线接C51的P0口)sbit rs=P2^0;sbit en=P2^2;sbit rw=P2^1; //如果硬件上rw接地,就不用写这句和后面的rw=0了sbit led=P2^6; //LCD背光开关//延时函数,后面经常调用void delay(uint xms)//延时函数,有参函数{uint x,y;for(x=xms;x>0;x--)for(y=110;y>0;y--);}/********液晶写入指令函数与写入数据函数,以后可调用**************//*在这个程序中,液晶写入有关函数会在DS1302的函数中调用,所以液晶程序要放在前面*/write_1602com(uchar com)//****液晶写入指令函数****{rs=0;//数据/指令选择置为指令rw=0; //读写选择置为写P0=com;//送入数据delay(1);en=1;//拉高使能端,为制造有效的下降沿做准备delay(1);en=0;//en由高变低,产生下降沿,液晶执行命令}write_1602dat(uchar dat)//***液晶写入数据函数****{rs=1;//数据/指令选择置为数据rw=0; //读写选择置为写P0=dat;//送入数据delay(1);en=1; //en置高电平,为制造下降沿做准备delay(1);en=0; //en由高变低,产生下降沿,液晶执行命令}lcd_init()//***液晶初始化函数****{write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据write_1602com(0x0c);//开显示不显示光标write_1602com(0x06);//整屏不移动,光标自动右移write_1602com(0x01);//清显示}/*******************************共阳LED段码表*******************************///unsigned char code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};/************************************************************** **************函数功能:AD转换子程序入口参数:CH(如果读取CH0,channel的值为0x01,如果读取CH1则channel的值为0x03)出口参数:adval*************************************************************** *************/unsigned char Adc0832(unsigned char channel) //AD转换,返回结果{unsigned char i;unsigned char dat=0;ADCLK=0;ADDIO=1;ADCS=0; //拉低CS端ADCLK=1;ADCLK=0; //拉低CLK端,形成下降沿1ADDIO=channel&0x1;//指定转换通道是CH1还是CH2,指定值位与0x1,取最后一位的值ADCLK=1;ADCLK=0; //拉低CLK端,形成下降沿2ADDIO=(channel>>1)&0x1;//指定值右移一位,再取最后一位的值ADCLK=1;ADCLK=0; //拉低CLK端,形成下降沿3ADDIO=1;for(i=0;i<8;i++){ADCLK=1;ADCLK=0; //形成一次时钟脉冲if(ADDIO)dat|= 0x80>>i; //收数据}ADCS=1; //拉低CS端ADCLK=1;ADDIO=1; //拉高数据端,回到初始状态return(dat); //return dat}//------输入电压要经过1/10分压后接到0832的CH端,显示值才能与实际电压相符合------------//LCD 电压显示子程序(第一行)void write_v1(uchar add,unsigned int dat)//向LCD写温度数据,并指定显示位置在第二行{uchar gw,sw,bai,qian;qian = dat/1000;//取得千位数字bai = dat%1000/100;//取得百位数字sw=dat%100/10;//取得十位数字gw=dat%10;//取得个位数字write_1602com(yh+add);//YH是头文件规定的值,指定显示位置write_1602dat(0x30+qian);write_1602dat(0x30+bai);write_1602dat(0x2e);//百位后面显示小数点,输入电压要经过1/10分压后接到0832的CH端,显示值才能与实际电压相符合write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码,指定显示内容//write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码}//LCD 电压显示子程序(第二行)void write_v2(uchar add,unsigned int dat)//向LCD写温度数据,并指定显示位置在第二行{uchar gw,sw,bai,qian;qian = dat/1000;//取得千位数字bai = dat%1000/100;//取得百位数字sw=dat%100/10;//取得十位数字gw=dat%10;//取得个位数字write_1602com(er+add);//er是头文件规定的值0x80+0x40,指定显示位置write_1602dat(0x30+qian);write_1602dat(0x30+bai);write_1602dat(0x2e);//百位后面显示小数点,输入电压要经过1/10分压后接到0832的CH端,显示值才能与实际电压相符合write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码,指定显示内容//write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码}//LCD显示电压前的CH1或者CH2子程序:void write_CH(uchar yw, uchar add,uchar dat)//{write_1602com(yw+add);//在第一行显示write_1602dat(0x56);//显示大写字母V//write_1602dat(0x43);//write_1602dat(0x48);write_1602dat(0x30+dat);//显示字母后缀上的数字write_1602dat(0x3d);//显示=号}/************************************************************** **************函数功能:数码管显示子程序入口参数:出口参数:*************************************************************** *************void delay1(void){int k;for(k=0;k<400;k++);}/************************************************************** **************函数功能:数码管显示子程序入口参数:k出口参数:*************************************************************** *************void display(int k){P2=0xfe;P0=tab[k/1000];delay1();P2=0xfd;P0=tab[k%1000/100];delay1();P2=0xfb;P0=tab[k%100/10];delay1();P2=0xf7;P0=tab[k%10];delay1();P2=0xff;}/************************************************************** **************函数功能:主程序入口参数:出口参数:*************************************************************** *************/void main(void){unsigned int adc1,adc2;lcd_init(); //调用液晶屏初始化子函数led=0; //打开LCD的背光电源while(1) //主循环{adc1=Adc0832(0x03);//读取CH1通道//adc=adc*0.1953;//display(adc); //显示AD值adc1=adc1*39.2156862745098;//换算成毫伏的数值write_CH(yh,0,1);//第一行开头显示CH1=,三个参数分别为第一行、从0位置开始、V后面的字是1write_v1(3,adc1);//显示温度,从第一行第4个字符位置adc2=Adc0832(0x01);//读取CH0通道//adc=adc*0.1953;//display(adc); //显示AD值adc2=adc2*39.2156862745098;//换算成毫伏的数值write_CH(er,0,2);//第二行开头显示CH0=,三个参数分别为第二行、从0位置开始、V后面的字是2write_v2(3,adc2);//显示温度,从第二行第4个字符后开始显示delay(3000);}}。
51单片机驱动ADC0832模数转换程序
-lcd1602显示
/*这个芯应用不多*/
#include ;
#define uchar unsigned char
#define uint unsigned int
uchar Chan0Value,Chan1Value;
sbit RS=P1^0; //1602各控制脚
sbit RW=P1^1;
sbit EN=P1^2;
sbit Cs0832= P2^0;
//0832各控制脚
sbit Clk0832= P3^6;
sbit Di0832= P3^7;
sbit Do0832= P3^7;
void delay1ms(unsigned int ms)//延时1毫秒(不够精确的)
{
int i,j;
for(i=0;i;>;i;
}
for(i=0;i<8;i++)
//从低到高取一次数
{
if(Do0832) Dat2|=0x01<<i;
Clk0832=1; //下降沿有效
Clk0832=0;
}
Cs0832=1;
Di0832=1;
Clk0832=1; //数据读取完成,释放所有数据线
if(Dat1==Dat2)
return Dat1; //校验两次数相等,输出
}
/*本程序与其他一般程序最大的不同就是要读两次
一次从最高位到最低位,一次从最低位到最高位,
两次所读值相等即为正常,可以输出*/
/******************************LCD1602*********** ***************************/
/*************************lcd1602程序
**************************/
void wr_com(unsigned char com)//写指令// { delay1ms(1);
RS=0;
RW=0;
EN=0;
P0=com;
delay1ms(1);
EN=1;
delay1ms(1);
EN=0;
}
void wr_dat(unsigned char dat)//写数据// { delay1ms(1);
RS=1;
RW=0;
EN=0;
P0=dat;
delay1ms(1);
EN=1;
delay1ms(1);
EN=0;
}
void lcd_init()//初始化设置//
{
delay1ms(15);
wr_com(0x38);delay1ms(5);
wr_com(0x80);delay1ms(5);
wr_com(0x01);delay1ms(5);
wr_com(0x06);delay1ms(5);
wr_com(0x0c);delay1ms(5);
}
void writevalue(uchar add,uchar dat) {
wr_com(0x80+add);
wr_dat(dat);
}
void zifuchuan(uchar *ch)
{
while(*ch!=0)
wr_dat(*ch++);
delay1ms(20);
}
void main(void)
{
lcd_init();
while(1)
{
Chan0Value=GetValue0832(0);
delay1ms(100);
Chan1Value=GetValue0832(1);
wr_com(0x80);
zifuchuan("Chanal 0:");
writevalue(10,Chan0Value/100+0x30);
writevalue(11,Chan0Value%100/10+0x30);
writevalue(12,Chan0Value%100%10+0x30);
wr_com(0x80+0x40);
zifuchuan("Chanal 1:");
writevalue(0x40+10,Chan1Value/100+0x30);
writevalue(0x40+11,Chan1Value%100/10+0x30); writevalue(0x40+12,Chan1Value%100%10+0x30); delay1ms(1000);
}
}
/*此程序只为调通ADC0832,没有对电压值进行转换
要想得到准确电压值,请把Chan0Value和Chan1Value 的值乘以5再除以255即可。
当某一通道没有输入而
悬空时,有可能会显示256的中间值128,这是干扰,可以不理会*/。