版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
PAGEPAGE39第13章单片机应用系统设计与接口技术例题简单键盘扫描程序清单:#defineucharunsignedchar#include<reg51.h> //*键盘扫描子程序voidkeys(){ ucharkeyc; P1=0xff; //置P1口输入状态 keyc=P1; //读入P1口状态 if(keyc!==0xff)//判断有否按键按下?{delay1ms(1));//10ms去抖动程序,在此略if(keyc!==0xff){if(keyc==0xfe){ …… // K0键操作程序 } elseif(keyc==0xfd) { …… // K1键操作程序 }…//略(K2~K6键对应的处理程序) elseif(keyc==0x7f) { …… // K7键操作程序 }}}}voidmain(){While(1){ keys();}}矩阵键盘扫描程序清单:#defineucharunsignedchar#include<reg51.h>bitflag=0x01; //定义按键标志ucharcol; //定义列号变量ucharscanword; //定义扫描字变量ucharkeyvalue; //定义键值变量voiddelay(intn) //*延时子程序{ for(;n>=0;n--);}voidkeyon() //*判键闭合子程序{ P1=0xF0; //列输出低电平 keyvalue=P1;//读行输入 keyvalue=~keyvalue;//keyvalue为0,无键按下;不为0,有键按下 keyvalue=keyvalue&0xF0;//}voidkeyscan() //键盘扫描子程序{ ucharswd; keyon(); //调用判键闭合子程序 if(keyvalue!=0) //有键闭合 { delay(1000); //去抖动 keyon(); if(keyvalue!=0) //去抖动,确认有键被按下,开始扫描 { scanword=0xfe; //设扫描字首列为0 col=0; //送首列号 while(scanword!=0xef) //判断4行是否都已扫描完 { swd=scanword; P1=swd; //扫描字从P1口送出 swd=P1; swd=swd&0xf0; if(swd==0xe0) //判断第一行是否有键 { keyvalue=0; //第1行首键号送keyvalue } elseif(swd==0xd0) //第1行无键闭合,转第2行 { keyvalue=0x04; //第2行首键号送keyvalue } elseif(swd==0xb0) //第2行无键闭合,转第3行 { keyvalue=0x8; //第3行首键号送keyvalue } elseif(swd==0x70) //第3行无键闭合,转第4行 { keyvalue=0x0c; //第4行首键号送keyvalue } else { col=col+1; //列号加1 scanword<<=1; //扫描字左移 flag=0; //清有键按下标志 continue; } } keyvalue=keyvalue+col; //计算键值 flag=1; //置有键按下标志 } }}定时扫描程序清单:voidtime_intt0(void)interrupt1 //*定时器中断服务程序,定时扫描键盘{ TL0=0xF0; TH0=0xD8; keyscan(); //此子程序见前例 }voidmain() //*主程序{ TMOD=0x01; //初始化定时器T0为方式1,定时10ms TL0=0xF0; TH0=0xD8; IE=0x82; TR0=1; while(1); //等待定时中断}矩阵式按键应用举例(1)任务说明:用矩阵键盘输入数字,在数码LED上显示。(2)硬件设计:本任务只用到一个共阴数码管,所以数码管显示的方法简单,P0口接数码管段选控制端。P2接4×4矩阵键盘,以P2.0-P2.3作行扫描线,以P2.4-P2.7作列扫描线。如图13.10所示。图13.10矩阵键盘应用电路(3)软件设计#include<reg51.h>#defineKEYP2#defineucharunsignedchar#defineuintunsignedintuchark;ucharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};//共阴极字形码ucharcodekey_code[]={0xee,0xed,0xeb,0xe7,0xde,0xdd,0xdb,0xd7,0xbe,0xbd,0xbb,0xb7,0x7e,0x7d,0x7b,0x77};//键码/*1ms延时子函数(1T、12T、主时钟不同时,需做调整)*/delay1ms(intt){inti,j;for(i=0;i<t;i++)for(j=0;j<120;j++);}/*键盘扫描子函数*/ucharkeyscan(){ucharX,Y,Z;ucharj;KEY=0xff;KEY=0x0f;//列扫描输出全“0if(KEY!=0x0f)//判断是否有键按下{delay1ms(10);//延时,软件去干扰if(KEY!=0x0f)//确认按键按下;{X=KEY;//保存列扫描时有键按下时状态(列扫描键码)KEY=0xf0;//行扫描输出全“0Y=KEY;//保存行扫描时有键按下时状态(行扫描键码)Z=X|Y;//键码=列扫描键码+行扫描键码for(j=0;j<=15;j++){if(Z==key_code[j])//查表得键值{k=j;return(k);}}}}elseKEY=0xff;//恢复扫描线为输入状态return(16);}/数码管显示子函数*/display(){if((P2&0x0f)!=0x0f)//判键是否按下{P0=table[k];}}/*主函数*/main(){P0=0x80;//数码管显示"."KEY=0xff; while(1) {keyscan(); display(); }}静态显示程序单片机系统中,常采用74HC595作为LED的静态显示接口。74HC595管脚如图13.13所示,该芯片内含8位串入、串/并出移位寄存器和8位三态输出锁存器。寄存器和锁存器分别有各自的时钟输入(SFTCLK和LCHCLK),都是上升沿有效。当SFTCLK从低到高电平跳变时,串行输入数据(SDI)移入寄存器;当LCHCLK从低到高电平跳变时,寄存器的数据置入锁存器。清除端(/RST)的低电平只对寄存器复位(SDO为低电平),而对锁存器无影响。当输出允许控制(/OE)为高电平时,并行输出(Q0~Q7)为高阻态,而串行输出(SDO)不受影响。74HC595最多需要5根控制线,即SDI、SFTCLK、LCHCLK、/RST和/OE。其中RST可以直接接到高电平,用软件来实现寄存器清零;如果不需要软件改变亮度,OE可以直接接到低电平,而用硬件来改变亮度。把其余三根线和单片机的I/O口相接,即可实现对LED的控制。数据从SDI口送入74HC595,在每个SFTCLK的上升沿,SDI口上的数据移入寄存器,在SFTCLK的第9个上升沿,数据开始从SDO移出。如果把第一个74HC595的SDO和第二个74HC595的SDI相接,数据即移入第二个74HC595中,照此一个一个接下去,可接任意多个。数据全部送完后,给LCHCLK一个上升沿,寄存器中的数据即置入锁存器。此时如果OE为低电平,数据即从并口Q0~Q7输出,把Q0~Q7与LED的8段相接,LED就可以实现显示了。要想软件改变LED的亮度,只需改变OE的占空比就行了。采用74HC595芯片与51单片机的连接4位数码管显示电路如图13.13所示。其中P1口的P1.5、P1.6、P1.7分别接到74HC595的SFTLCK、LCHCLK和SDI引脚,P1.1接74HC595的/OE,用于控制显示亮度。图13.13静态显示的LED接口电路(3)程序实现#include<reg51.h>unsignedcharcode7[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//定义显示码sbitsftclk=P1^6; //移位寄存器时钟sbitlchclk=P1^5; //锁存器时钟sbitsdi=P1^7; //输入端口sbitOE=P1^0; //数据输出允许位标志/*清“0”子函数clrdsp() { unsignedchari; for(i=0;i<32;i++) { sftclk=0; sdi=0; sftclk=1; } }/*显示子函数*/display() { unsignedchari,j,segment; for(i=0;i<4;i++) { segment=code7[i]; lchclk=0; for(j=0;j<8;j++) { sftclk=0; segment<<=1; sdi=CY; sftclk=1; } lchclk=1;//将移位寄存器数据置入锁存器中 }}/*主函数*/voidmain() { OE=1; //不允许输出 clrdsp(); display(); OE=0; //允许输出 }数码管动态扫描显示程序的实现程序功能:6位数码管显示“543210”#include<reg51.h>#defineucharunsignedchar#defineled_dataP0 //数码管段选#defineled_bitP2 //数码管位选UcharcodeLEDValue[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00}; //共阴数码管显示码"0"-"9","熄灭"uchardatascan_con[6]={0x01,0x02,0x04,0x08,0x10,0x20};//列扫描字/*1ms延时子函数*/delay1ms(intt) {inti,j;for(i=0;i<t;i++) for(j=0;j<120;j++) ;}/*数码管显示子函数*/display() {uchark;for(k=0;k<6;k++){led_data=LEDValue[k]; //6位数码管依次显示01...5led_bit=scan_con[k];delay1ms(1);led_bit=0x00;//数码管点亮切换时,关显示}}/*主函数*/main(); { while(1) { display(); }}LCD1602程序的实现程序功能:第一行显示:Welcome,第二行显示:(1)程序流程图主程序流程如图13.18示。图13.18主程序流程图(2)源程序#include<reg51.h>#include<intrins.h> //声明了_nop_(void)#defineucharunsignedchar#defineuintunsignedinttypedefbitBOOL;/*定义控制引脚*/sbitrs=P2^0; //RSsbitrw=P2^1; //读写选择RWsbite=P2^2; //使能信号Eucharcodedis1[]={"Welcome!"}; //定义第一行显示字符ucharcodedis2[]={"/"}; //定义第二行显示字符/*延时子函数*/voiddelay(ucharms) {uintj;while(ms--){for(j=0;j<750;j++);}}/*判别LCD忙碌状态子函数*/BOOLlcd_bz() {BOOLresult;rs=0;rw=1;e=1;result=(BOOL)(P0&0x80); //强迫P0&0x80的结果数据类型为位变量e=0;returnresult;}/*写入指令数据到LCD子函数*/voidlcd_wcmd(ucharcmd) //*写入指令数据到LCD{while(lcd_bz());rs=0;rw=0;e=0;P0=cmd;e=1;e=0;}/*设定LCD显示位置子函数*/voidlcd_start(ucharstart) {lcd_wcmd(start|0x80); //显示位置+写显示位置的代码(80H)}/*写入显示字符数据到LCD子函数*/voidlcd_data(uchardat) {while(lcd_bz());rs=1;rw=0;e=0;P0=dat;e=1;e=0;}/*LCD初始化设定子函数*/voidlcd_init() {delay(15);lcd_wcmd(0x38); //设定LCD为16×2显示,5×7点阵,8位数据接口delay(2);lcd_wcmd(0x0c); //开显示,不显示光标delay(2);lcd_wcmd(0x06); //地址计数器递增计数,显示屏不移动delay(2);lcd_wcmd(0x01); //清显示屏delay(2);}/*主函数*/voidmain() {uchari;lcd_init(); //初始化LCDdelay(20);lcd_start(4); //设置显示位置为第一行的第5个字符i=0;while(dis1[i]!='\0'){ //显示第一行字符lcd_data(dis1[i]);i++;}lcd_start(0x42); //设置显示位置为第二行第3个字符i=0;while(dis2[i]!='\0'){lcd_data(dis2[i]); //显示第二行字符i++;}while(1);}带中文字库的LCD12864与51单片机接口(并行)的软件设计(1)程序功能:在16列ASCII字符(8列中文)×4行的液晶显示屏上显示"SMG12864ZK","中文字符图形点阵","液晶显示模块","长沙太阳人SUNMAN";显示自定义字符;图形模式图片显示。程序清单#include<reg51.h>#include<intrins.h>/*子函数声明*/voidexdelay(void);//延时子程序voidputchar(unsignedintc);//定位写字符子程序voidputstr(unsignedcharcode*s);//显示字符串子程序,字符码为0时退出voidputstrxy(unsignedcharcx,unsignedcharcy,unsignedcharcode*s);voidsetcharcgram(unsignedcharcindex,unsignedcharcode*s);//设置自定义字符点阵voidcharcursornext(void);//置字符位置为下一个有效位置子程序voidputimage(unsignedcharcode*s);//显示图形子程序voidputsizeimage(unsignedcharXSIZE,unsignedcharYSIZE,unsignedcharcode*s);//显示指定大小的图形子程序voidglcdpos(void);//写入绘图区域内部RAM指针子程序voidcharlcdpos(void);//设置(CXPOS,CYPOS)内部DDRAM地址的子程序voidlcdreset(void);//液晶显示控制器初始化子程序voiddelay3ms(void);//延时3MS子程序voidlcdon(void);//LCD显示开启子程序voidlcdoff(void);//LCD显示关闭子程序voidlcdgraphon(void);//绘图区域显示开启子程序voidlcdgraphoff(void);//绘图区域显示关闭子程序unsignedcharlcdrd(void);//从液晶显示控制器读数据voidlcdwd(unsignedchard);//送图形数据子程序voidlcdwc(unsignedcharc);//送指令子程序voidlcdwaitidle(void);//控制器忙检测子程序/*定义控制引脚*/sbitRSPIN=P3^2;//RS对应单片机引脚sbitRWPIN=P3^3;//RW对应单片机引脚sbitEPIN=P3^4;//E对应单片机引脚/*定义CXPOS、CYPOS变量,用于指示当前操作字符的位置*/unsignedcharCXPOS;//列方向地址指针(用于charlcdpos子程序)unsignedcharCYPOS;//行方向地址指针(用于charlcdpos子程序)/*定义CXPOS、CYPOS变量,用于指示绘图区域RAM的位置*/unsignedcharGXPOS;//列方向地址指针(用于glcdpos子程序)unsignedcharGYPOS;//行方向地址指针(用于glcdpos子程序)/*定义自定义字符的编码值*/#defineUSERCHAR1CODE0xffff//自定义字符1代码#defineUSERCHAR2CODE0xfffd//自定义字符2代码#defineUSERCHAR3CODE0xfffb//自定义字符3代码#defineUSERCHAR4CODE0xfff9//自定义字符4代码/*自定义字符“1”unsignedcharcodeCHAR1CGRAMTAB[]={0x00,0x0f,0x00,0x7f0x01,0xf0,0x03,0xc0,0x07,0x0f,0x0e,0x3f,0x1c,0xfe,0x39,0xfc,0x33,0xfc,0x73,0xfe,0x67,0xff,0x67,0xe7,0xcf,0xe3,0xcf,0xe1,0xcf,0xe4,0xc0,0x06};/*自定义字符“2”unsignedcharcodeCHAR2CGRAMTAB[]={0xf0,0x00,0xfe,0x00,0x0f,0x80,0x03,0xc0,0xf0,0xe0,0xfc,0x70,0x7f,0x38,0x3f,0x9c,0x3f,0xcc,0x7f,0xce,0xff,0xe6,0xe7,0xe6,0xc7,0xf3,0x87,0xff,0x27,0xff,0x60,0x03};/*自定义字符“3”unsignedcharcodeCHAR3CGRAMTAB[]={0xc0,0x07,0xff,0xe7,0xff,0xe7,0xcf,0xe7,0x67,0xe7,0x67,0xff,0x73,0xff,0x33,0xff,0x39,0xff,0x1c,0xff,0x0e,0x3f,0x07,0x0f,0x03,0xc0,0x01,0xf0,0x00,0x7f,0x00,0x0f};/*自定义字符“4”unsignedcharcodeCHAR4CGRAMTAB[]={0xe0,0x03,0xe7,0xf3,0xe7,0xf3,0xe7,0xf3,0xe7,0xe6,0xff,0xe6,0xff,0xce,0xff,0xcc,0xff,0x9c,0xff,0x38,0xfc,0x70,0xf0,0xe0,0x03,0xc0,0x0f,0x80,0xfe,0x00,0xf0,0x00};/*定义图片库点阵代码*/unsignedcharcodeImg_SUNMAN_128x64[]={略,实际使用时由SUNMAN图形点阵代码生成器.EXE自动生成图片的库点阵代码};/*主函数*/voidmain(void){while(1){lcdreset();//初始化液晶显示控制器charlcdfill('');//显示清屏//在(2,0)字符位置显示"SMG12864ZK"putstrxy(2,0,"SMG12864ZK");//在(2,0)位置开始显示字符串exdelay();//延时约300mSexdelay();//延时约300mS//在(0,1)字符位置显示"中文字符图形点阵"putstrxy(0,1,"中文字符图形点阵");//在(0,1)位置开始显示字符串exdelay();//延时约300mSexdelay();//延时约300mS//在(2,2)字符位置显示"液晶显示模块"putstrxy(2,2,"液晶显示模块");//在(2,2)位置开始显示字符串exdelay();//延时约300mSexdelay();//延时约300mS//在(0,3)字符位置显示"长沙太阳人SUNMAN"putstrxy(0,3,"长沙太阳人SUNMAN");//在(0,3)位置开始显示字符串exdelay();//延时约300mSexdelay();//延时约300m//在(4,0)(5,0)(4,1)(5,1)字符位置显示自定义字符1,2,3,4setcharcgram(0,CHAR1CGRAMTAB);//装入自定义字符字符点阵setcharcgram(1,CHAR2CGRAMTAB);setcharcgram(2,CHAR3CGRAMTAB);setcharcgram(3,CHAR4CGRAMTAB);//装入自定义字符字符点阵CXPOS=4,CYPOS=0;putchar(USERCHAR1CODE);exdelay();//延时约300mSputchar(USERCHAR2CODE);exdelay();//延时约300mSCXPOS=4,CYPOS=1;putchar(USERCHAR3CODE);exdelay();//延时约300mSputchar(USERCHAR4CODE);exdelay();//延时约300mSexdelay();//延时约300mS//在(0,0)点阵位置显示图片charlcdfill('');//显示清屏lcdgraphon();//开图形模式GXPOS=0,GYPOS=0;putimage(Img_SUNMAN_128x64);exdelay();//延时约300mSexdelay();//延时约300mSglcdfill(0);//图形区域清屏lcdgraphoff();//关图形模式}}/*300mS延时子程序*/voidexdelay(void)//1T,@18.432MHz,由STC-ISP软件自动生成{unsignedchari,j,k; _nop_(); _nop_(); i=22; j=3; k=227; do { do { while(--k); }while(--j); }while(--i);}/*在(XPOS,YPOS)位置写单个字符点阵子程序*/voidputchar(unsignedintc){unsignedchard;if(c>128)//字符码大于128表示为汉字{if((CXPOS&0x1)==1)//写汉字时,CXPOS字符位置在奇数位置,则{lcdwd('');//自动补添一个空格对齐后再显示汉字charcursornext();//置字符位置为下一个有效位置}charlcdpos();if((c&0xff00)==0xff00)//若高位字节为0FFH则表示为自定义字符{c=0xffff-c;//则转换为ST7920的字符码}lcdwd(c/256);//写高位字符charcursornext();lcdwd(c&0xff);//写低位字符charcursornext();}else//字符码小于128表示为ASCII字符{charlcdpos();if((CXPOS&0x1)==1)//写ASCII字符时,CXPOS字符位置在奇数位置,则{d=lcdrd();//读高位字符charlcdpos();lcdwd(d);//重新写高位字符lcdwd(c);}else{lcdwd(c);//写ASCII字符时,CXPOS字符位置在偶数位置,则lcdwd('');//直接写入,同时自动补显一个空格.}charcursornext();//置字符位置为下一个有效位置}}/*写字符串点阵子程序*/voidputstr(unsignedcharcode*s)//显示字符串子程序,字符码为0时退出{unsignedintc;while(1){c=*s;s++;if(c==0)break;if(c<128){putchar(c);}else{putchar(c*256+*s);s++;}}}/*在(cx,cy)字符位置写字符串子程序*/voidputstrxy(unsignedcharcx,unsignedcharcy,unsignedcharcode*s){//在(cx,cy)字符位置写字符串子程序CXPOS=cx;//置当前X位置为cxCYPOS=cy;//置当前Y位置为cyputstr(s);}/*将*s所指32字节点阵代码写到自定义字符cindex(0-3)中子程序*/voidsetcharcgram(unsignedcharcindex,unsignedcharcode*s){unsignedchari;lcdwc(0x34);//扩充指令集,图形模式关闭lcdwc(0x02);//SR=0激活CGRAMlcdwc(0x30);//恢复为基本指令集lcdwc(((cindex&0x3)<<4)|0x40);//设置CGRAM地址for(i=0;i<32;i++,s++)//写点阵数据{lcdwd(*s);}}/*在(GXPOS,GYPOS)位置绘制XSIZE列及YISZE行点阵的图形子程序*/voidputsizeimage(unsignedcharXSIZE,unsignedcharYSIZE,unsignedcharcode*s){unsignedcharlx,ly,x;x=GXPOS;for(ly=0;ly<YSIZE;ly++,GYPOS++){for(GXPOS=x,lx=0;lx<XSIZE;){if((GXPOS&0x08)==0){glcdpos();}lcdwd(*s);s++;lx+=8;GXPOS+=8;}}GXPOS=x;}/*在(XPOS,YPOS)位置绘制XSIZE[*s]列及YISZE[*(s+1)]行点阵的图形[*(s+2)]子程序*/voidputimage(unsignedcharcode*s){unsignedcharXSIZE,YSIZE;XSIZE=*s;s++;YSIZE=*s;s++;putsizeimage(XSIZE,YSIZE,s);}/*设置坐标点(CXPOS,CYPOS)位置对应的内部RAM地址子程序*/voidcharlcdpos(void){unsignedcharddaddr;CXPOS&=0xf;//X位置范围(0到15)ddaddr=CXPOS/2;if(CYPOS==0)//(第一行)X:lcdwc(ddaddr|0x80);//DDRAM:8087Helseif(CYPOS==1)//(第二行)X:lcdwc(ddaddr|0x90);//DDRAM:9007Helseif(CYPOS==2)//(第三行)X:lcdwc(ddaddr|0x88);//DDRAM:888FHelse//(第四行)X:lcdwc(ddaddr|0x98);//DDRAM:989FH}/*置字符位置为下一个有效位置子程序*/voidcharcursornext(void){CXPOS++;//字符位置加1CXPOS&=0x0f;//字符位置CXPOS的有效范围为(0到15)if(CXPOS==0)//字符位置CXPOS=0表示要换行{CYPOS++;//行位置加1CYPOS&=0X3;//字符位置CYPOS的有效范围为(0到3)}}/*液晶显示控制器初始化子程序*/voidlcdreset(void){lcdwc(0x33);//接口模式设置delay3ms();//延时3MSlcdwc(0x30);//基本指令集delay3ms();//延时3MSlcdwc(0x30);//重复送基本指令集delay3ms();//延时3MSlcdwc(0x01);//清屏控制字delay3ms();//延时3MSlcdon();//开显示}/*3mS延时子程序*/voiddelay3ms(void)//1T,@18.432MHz,由STC-ISP软件自动生成{unsignedchari,j; i=54; j=199; do { while(--j); }while(--i);}/*设置(GXPOS,GYPOS)对应绘图区域内部RAM指针子程序*/voidglcdpos(void){lcdwc(0x36);//扩展指令集lcdwc((GYPOS&0x1f)|0x80);//先送Y地址if(GYPOS>=32)//再送X地址lcdwc((GXPOS/16+8)|0x80);elselcdwc((GXPOS/16)|0x80);lcdwc(0x30);//恢复为基本指令集}/*开启LCD显示子程序*/voidlcdon(void){lcdwc(0x30);//设置为基本指令集lcdwc(0x0c);}/*关闭LCD显示子程序*/voidlcdoff(void){lcdwc(0x30);//设置为基本指令集lcdwc(0x08);}/*开启绘图区域显示子程序*/voidlcdgraphon(void){lcdwc(0x36);lcdwc(0x30);//恢复为基本指令集}/*关闭绘图区域显示子程序*/voidlcdgraphoff(void){lcdwc(0x34);lcdwc(0x30);//恢复为基本指令集}/*从液晶显示控制器读数据子程序*/unsignedcharlcdrd(void){unsignedchard;lcdwaitidle();//ST7920液晶显示控制器忙检测RSPIN=1;//RS=1RW=1E=高脉冲RWPIN=1;EPIN=1;_nop_();d=P1;EPIN=0;returnd;}/*向液晶显示控制器写数据子程序*/voidlcdwd(unsignedchard){lcdwaitidle();//ST7920液晶显示控制器忙检测P1=d;RSPIN=1;//RS=1RW=0E=高脉冲RWPIN=0;EPIN=1;_nop_();EPIN=0;}/*向液晶显示控制器写指令子程序*/voidlcdwc(unsignedcharc){lcdwaitidle();//ST7920液晶显示控制器忙检测P1=c;RSPIN=0;//RS=0RW=0E=高脉冲RWPIN=0;EPIN=1;_nop_();EPIN=0;}/*忙检测子程序*/voidlcdwaitidle(void){unsignedchari;P1=0xff;RSPIN=0;RWPIN=1;EPIN=1;for(i=0;i<20;i++)if((P1&0x80)!=0x80)break;//D7=0空闲退出EPIN=0;}数字温度计电路实现将单片机最小系统、DS18B20、数码显示电路组合在一起,构成数字温度计电路,其仿真电路如图13.36。DS18B20的DQ端接P3.2,数码显示的段控制端a~h接P0.0~P0.7,位控制端由低到高依次接P2.0~P2.5。图13.36温度计电路源程序清单#include"reg51.H"#include"intrins.H"ucharcodedisp[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};typedefunsignedcharBYTE;#defineuintunsignedintsbitDQ=P3^2;//DS18B20的数据口位P3.2BYTETPH;//存放温度值的高字节BYTETPL;//存放温度值的低字节uinttemp;voidDelayX10us(BYTEn);voidDS18B20_Reset();voidDS18B20_WriteByte(BYTEdat);BYTEDS18B20_ReadByte();/*主函数*/voidmain(){BYTEcom=1;//设定DS18B20检测间隔while(1){ com--; if(com==0) { com=20;DS18B20_Reset();//设备复位 DS18B20_WriteByte(0xCC);//跳过ROM命令 DS18B20_WriteByte(0x44);//开始转换命令 while(!DQ);//等待转换完成 DS18B20_Reset();//设备复位 DS18B20_WriteByte(0xCC);//跳过ROM命令 DS18B20_WriteByte(0xBE);//读暂存存储器命令 TPL=DS18B20_ReadByte();//读温度低字节 TPH=DS18B20_ReadByte();//读温度高字节 temp=(TPH*256+TPL)*25;//高8位温度数据和低8位温度数据合并16位 tem=tem>>2//温度数据处理:temp×0.0625×100 }P2=0xFF; //小数部分 P0=disp[temp%1000%100%10]; P2=0xfb; DelayX10us(100); P2=0xFF; P0=disp[temp%1000%100/10]; P2=0xf7; DelayX10us(100); P2=0xFF; //整数部分 P0=disp[temp%1000/100]+0x80; P2=0xef; DelayX10us(100); P2=0xFF; P0=disp[temp/1000]; P2=0xdf; DelayX10us(100); }}/*延时n×10微秒子程序*/voidDelayX10us(BYTEn)//1T,@18.432MHz{while(n--){ unsignedchari;_nop_();_nop_();i=43;while(--i);}}/*DS18B20复位子程序*/voidDS18B20_Reset(){CY=1;while(CY){DQ=0;//送出低电平复位信号DelayX10us(24);//延时至少480usDelayX10us(24);DQ=1;//释放数据线DelayX10us(6);//等待60usCY=DQ;//检测存在脉冲DelayX10us(24);//等待设备释放数据线DelayX10us(18);}}/*DS18B20读1字节数据子程序*/BYTEDS18B20_ReadByte(){BYTEi;BYTEdat=0;for(i=0;i<8;i++)//8位计数器{dat>>=1;DQ=0;//开始时间片DelayX10us(1);//延时等待DQ=1;//准备接收DelayX10us(1);//接收延时if(DQ)dat|=0x80;//读取数据DelayX10us(6);//等待时间片结束}returndat;}/*向DS18B20写1字节数据子程序*/voidDS18B20_WriteByte(BYTEdat){chari;for(i=0;i<8;i++)//8位计数器{DQ=0;//开始时间片DelayX10us(1);//延时等待dat>>=1;//送出数据DQ=CY;DelayX10us(6);//等待时间片结束DQ=1;//恢复数据线DelayX10us(1);//恢复延时}}I2C.h源程序清单:#include<reg51.h>sbitscl=P1^0;//定义串行I/O口sbitsda=P1^1;bitflag,flag1;//flag为返回应答标志,0为应答,1为非应答;//flag1为接收结束标志/*延时子程序*/voiddelay(void) //1T,@18.432MHz{unsignedchari;_nop_();_nop_();i=20;while(--i);}/*I2C总线起始条件子程序*voidI_start(void) {sda=1;scl=1;delay();sda=0;delay();scl=0;}/*I2C总线停止条件子程序*voidI_stop(void) {sda=0;scl=1;delay();sda=1;delay();}/*字节数据传送子程序*/bitI_send(ucharI_data) //返回应答标志(flag){datauchari;for(i=0;i<8;i++){sda=(bit)(I_data&0x80); I_data=I_data<<1; scl=1; delay(); scl=0;} sda=1;//准备接收ACK(应答)位 scl=1; flag=0; if(sda==0)flag=0;//开始接收ACK(应答)位 elseflag=1;//返回(~I_clock()); scl=0; return(flag);//返回应答标志;}/*字节数据接收子程序*/ucharI_receive(void) //*字节数据接收子程序{datauchari;ucharI_data=0;sda=1;for(i=0;i<8;i++){I_data*=2;//乘2,相当于左移一位。接收数据的顺序是由高到低scl=0;delay();scl=1;if(sda==1)I_data++;}scl=0;sda=0;if(flag1==0){Scl=1;delay();Scl=0;}//不是最后一个接收数据,发应答信号else{sda=1;scl=1;delay();scl=0;flag1=0;}//是最后一个接收数据,发非应答信号return(I_data);//返回接收数据}电子时钟的源程序清单#include<reg51.h>#include<stdlib.h>#include<I2C.h>//包含I2C通信IO口模拟#defineucharunsignedchar#defineled_dataP0 //数码管段选#defineled_bitP2 //数码管位选idataucharrom_sed[9]; //当前发送值idataucharrom_rec[7]; //接收值ucharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};uchardatascan_con[6]={0x01,0x02,0x04,0x08,0x10,0x20};//列扫描字uchardatadis[6]={0x00,0x00,0x00,0x00,0x00,0x00};//显示单元数据,共6个/*1ms延时子程序*/delay1ms() //1T,@18.432MHz1ms延时子程序{unsignedchari,j; i=18; j=235; do { while(--j); }while(--i);}/*数码管显示子程序*/display() { uchari;dis[0]=rom_rec[0]&0x0f;//BCD码转十进制取低位dis[1]=rom_rec[0]>>4;//BCD码转十进制高位右移4位dis[2]=rom_rec[1]&0x0f;dis[3]=rom_rec[1]>>4;dis[4]=rom_rec[2]&0x0f;dis[5]=rom_rec[2]>>4; for(i=0;i<6;i++) { led_data=table[dis[i]];led_bit=scan_con[i];delay1ms(1);led_bit=0x00; }}/*pcf8563初始化子程序*/initializa() {datauchari;rom_sed[0]=0x00; //秒:0rom_sed[1]=0x00; //分:0rom_sed[2]=0x12; //时:12rom_sed[3]=0x01;//日:1rom_sed[4]=0x01;//星期:rom_sed[5]=0x01;//月:1rom_sed[6]=0x06;//年:2006rom_sed[7]=0xb0;//报警分设定:30rom_sed[8]=0x99;//报警时设定:19for(i=0;i<255;i++)delay();I_start();if(~I_send(0xa2)) //pcf_write地址{if(~I_send(0x02)) //pcf_status寄存器地址{for(i=0;i<9;i++){if(~I_send(rom_sed[i]));else;}I_stop();}else;}else;}/*读pcf8563子程序*/pcf8563() {datauchari;I_start();if(~I_send(0xa2)) //pcf_write地址 { if(~I_send(0x02)) //pcf_status寄存器地址 { I_start();if(~I_send(0xa3)) //写状态寄存器 { for(i=0;i<7;i++) { if(i==6)flag1=1; elseflag1=0; rom_rec[i]=I_receive(); switch(i) { case1:rom_rec[i]=rom_rec[i]&0x7f;break; case2: case3:rom_rec[i]=rom_rec[i]&0x3f;break; case4:rom_rec[i]=rom_rec[i]&0x07;break; case5:rom_rec[i]=rom_rec[i]&0x9f;break;default:break; } } I_stop(); }}}}/*主函数*/main() {initializa();while(1){pcf8563();display();}}利用单片机输出PWM脉冲控制直流电机的速度(1)程序功能本程序可输出周期为1/250Hz=4000s、占空比可变的PWM脉冲,P1.0接按键K_START用于启、停控制,P1.1接按键K_DIRECTION用于正、反转控制,P1.2接按键K_UP用于增加占空比,P1.3接按键K_DOWN用于减小占空比,P1.4、P1.5分别接正、反转控制电路的驱动控制端(如图13.43的ZDJ_A、ZDJ_B控制端)。直流电机控制电路图(利用Proteus软件绘制)如图13.46所示。图13.46直流电机控制电路(3)程序设计设机器振荡频率为12MHz,则机器周期为1s,用定时器T0产生200s定时时间作为定时脉冲,一个PWM周期为20个定时脉冲,通过控制高电平与低电平的脉冲数即可改变PWM输出的占空比。源程序清单如下:#include<reg52.h>#include<string.h>#defineucharunsignedchar#defineuintunsignedint#defineLed_wxP2#defineLed_dxP0/*定义变量*/uchar pwm=20; //定义pwm周期数uchar pwmH=1; //定义高电平脉冲个数计数器ucharcounter=0; //定义脉冲个数计数器ucharLedplay[6];//定义数据存放缓存区ucharbn=0; //定义显示数据缓冲区的位置变量bitM=1;//定义PWM输出的逻辑电平bitSW=1;//定义启停控制变量bitLR=0;//定义左、右转控制变量/*定义端口*/sbitK_START=P1^0; //定义启停控制引脚sbitK_DIRECTION=P1^1;//定义左、右转控制引脚sbitK_UP=P1^2;//定义加速控制引脚sbitK_DOWN=P1^3; //定义减速控制引脚sbitM1=P1^4;//定义电机驱动控制引脚sbitM2=P1^5;//定义电机驱动控制引脚/*定义数码管的字形码与字位码*/ucharcodeno[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x38,0x77,0x40};//数字(0~9),字符(L、R、-)对应的显示码ucharcodewex[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};//字位码/*短延时子程序(可变)*/voidDelay(unsignedinti) {while(i--);}/*长延时子程序(可变)*/voidDelayM(unsignedintt) { unsignedchari; while(--t!=0) { for(i=0;i<120;i++); }}/*字符载入子程序*/voidputin(intu) //将字符装入显示寄存器{ Ledplay[bn]=no[u]; bn++;//换下一个显示缓冲字节 }/*寄存器清空子程序*/voidclearRAM(void){//6个寄存器清空(0x00) Uchara;//定义变量用于清空数据指针 for(a=0;a<6;a++){ Ledplay[a]=0;//将指向的寄存器清空 }}/*数码管显示子程序*/voidledxs(void) { uchari; ucharDate=0; ucharwx=0; for(i=0;i<6;i++) //扫描数码管1~6位 { Date=wex[i]; Date=Date&0x3f; //取低六位数据 wx=Led_wx&0xc0|Date; //屏蔽高两位端口 Led_wx=wx; //送数据 Led_dx=Ledplay[i]; DelayM(2); }}/*定时器T0初始化子程序*/voidTime0_int(void) { TMOD=0X02; TH0=56; TL0=56; ET0=1; EA=1; TR0=1;}/*T0中断服务子程序*/voidTime0()interrupt1using1{ counter++; if (counter>=pwmH) { M=0; } if(counter==pwm) { counter=0; M=1;}}/*主函数*/main(){ Time0_int(); while(1){//按键处理 if(K_START==0) //检测开始/停止按键 { DelayM(20); //延时去抖 if(K_START==0) { SW=~SW; } while(K_START==0); //等待键释放 if(K_DIRECTION==0) //检测左转/右转按键 { DelayM(20); //延时去抖 if(K_DIRECTION==0) { LR=~LR; } while(K_DIRECTION==0); //等待键释放 } if(K_UP==0) //检测加速按键 { DelayM(20); //延时去抖 if(K_UP==0) { pwmH++; if(pwmH==pwm) { pwmH=pwm-1; } } while(K_UP==0); } if(K_DOWN==0) //检测减速按键 { DelayM(20); //延时去抖 if(K_DOWN==0) { pwmH--; if(pwmH==0) { pwmH=1; } } while(K_DOWN==0); } if(SW==0)//电机停止,关显示 { M1=0; M2=0; bn=0; clearRAM(); } if(SW==1)//电机启动 { bn=0; clearRAM(); putin(pwm%10);//显示pwm个位 putin(pwm/10);//显示pwm十位 putin(12);
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 施工机械进退场调度保障实施方案
- 空气净化器滤网更换周期安排方案
- 金融消息队列回放验证流程文档
- 物流集散区后段流水排产控制制度
- 雨季施工临时排水保障措施文件
- 手术部位标识核查操作规范
- 美术三年级下册18 泥条小陶罐教学设计及反思
- 回归能力指标追踪告警方案手册
- 台风灾害避险场所规划与建设
- 移动端版本年度迭代规划方案
- 普通地质学教材
- 考研清华大学431金融学综合真题回忆版
- 2023届高考作文复习:寓言类材料作文审题立意写作课件(共17张PPT)
- 2023年河南地矿职业学院单招考试职业适应性测试模拟试题及答案解析
- YY 0068.1-2008医用内窥镜硬性内窥镜第1部分:光学性能及测试方法
- GB/T 2653-2008焊接接头弯曲试验方法
- GB 5009.266-2016食品安全国家标准食品中甲醇的测定
- FZ/T 52004-2007充填用中空涤纶短纤维
- 大型设备说明-涂胶显影机第1台
- 科技创新引领新时代-三次科技革命及其影响下的社会发展-高三统编版(2019)历史一轮复习
- 滑坡防治技术课件
评论
0/150
提交评论