还剩24页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
电子路线专题实验II
一、实验要求L认真阅读学习系统路线及相关资料2,将键盘阵列定义为
0.
1.2----E.F,编程实现将键盘输入内容显示在LCD显示器上
3.编程实现将日历、时钟显示在LED显示屏上(注意子细阅读PCF8563资料),日历、时钟轮回显示
4.利用D/A转换通道(下行通道)实现锯齿波发生器;输出(1〜5V)固定电压转换成(4〜20mA)电流
5.利用A/D转换通道(上行通道)实现数据采集,将采集信号显示在LED屏上程序要求分别具有平均值滤波、中值滤波和滑动滤波功能
6.将按键阵列定义成与16个语音段对应,编写程序,实现按键播放不同的语音段
二、实验设计思路本次实验用c语言实现,主要包括LCD,LED,AD,DA,日历芯片,测温传感芯片受到嵌入式系统实验的启示,将LCD,LED,12c总线协议,键盘扫描模块接口写成一个文件库(放在library文件夹下),尽量做到调用时与底层硬件无关通过调用库文件中的函数,实现代码的重用性键盘,LCD的代码由于与嵌入式实验具有相通之处,因此可将高层的函数(与底层硬件无关的函数)方便地移植过来
三、实验设计:
1.矩阵键盘扫描模块4义4的矩阵键盘,通过扫描可得到按下键的行列值,将行列值转换为相应的对应数字0~F函数GetKey()实现获得按键的键值对于键盘模块对于对按键的键值识别主要是通过两次扫描而取得对于第一次扫描,给四行键全部赋予1,然后读回键盘值,对于第二次扫描,逐行为键盘送1,每次送1后再读回键盘值,若非零,说明此行有键按下,最终确定键值通过调用GetKey函数构造GetChar函数,实现获取键盘字符的功能通过调用GetChar函数构造GetDec()函数,实现获取键盘输入整数的功能,整数范围在0〜99999有按C键回退一格,按E清空当前未完输入,按下键结束输入的功能unsigned char key_asc2;key_asc2=ASC2_Value_Table[key];return key_asc2;
4.12C总线协议12c总线是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据12c总线在传送数据过程中共有三种类型信号,它们分别是开始信号、结束信号和应答信号开始信号SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据结束信号SCL为低电平时,SDA由低电平向高电平跳变,结束传送数据应答信号接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断若未收到应答信号,由判断为受控单元浮现故障sbit SCL=P1AO;sbitSDA=PlAl;ti〃*功能启动I2C总线If5^^void i2c_startSDA=1;SCL=1;_nop_;_nop_;SDA=0;_nopj;_nop_;SCL=O;〃*功能住手I2C总线jtvoid i2c_stopSDA=0;SCL=O;_nop_;_nop_;SCL=1;_nopj;_nop_;SDA=1;KtK,〃*功能应答12c总线KtK,bit i2c_rec_ackbit ack_flag;SDA=1;_nop_;_nopj;SCL=1;_nopj;_nop_;ifSDA==Oack_flag=l;elseack_flag=O;SCL=O;return ack-flag;void i2c_send_ackvoidSDA=0;_nop_;_nop_;SCL=1;_nop_;_nop_;SCL=O;_nop_;_nop_;SDA=1;ttt/〃*功能无应答12c总线ttvoid i2c_send_noackSDA=1;_nop_;_nop_;SCL=1;_nopj;_nopj;SCL=O;fKt,//*功能:往12c总线发送数据,,^L*gf*TQ^T1JjQvoid i2c_send_byteunsigned chardata_byteunsigned char i;fori=0;i8;i++SDA=bitdata_byte0x80;_nop;_nop_;SCL=1;_nop_;_nop_;SCL=O;data_byte«=l;K,4tli4tlif,〃*功能从12c总线接受数据K,uK^T**T^—]、^T*•JT*unsigned chari2c_rec_byteunsigned chari,temp;temp=O;fori=0;i8;i++temp«=l;SCL=1;_nop_;temp|=0x01;_nop_;ifSDA==lSCL=0;returntemp;K,t,〃*功能往12c总线上器件指定地址写字节的数据K,t,bit i2c_write_byteunsigned charsla,unsigned chardata_addr,unsigned chardata_bytei2c_start;//发送12C START信号i2c_send_bytesla;//发送器件从地址ifi2c_rec_ack==0//检测应答信号return0;//发送数据地址i2c_send_bytedata_addr;//检测应答信号ifi2c_rec_ack==0return0;i2c_send_bytedata_byte;ifi2c_rec_ack==0return0;//发送I2CSTOP信号i2c_stop;return1;//〃*功能往12c总线上器件指定地址开始写指定长度的数据//*ptr,unsigned charlen//发送12C START信号i2c_start;//发送器件从地址i2c_send_bytesla;//检测应答信号ifi2c_rec_ack==0bit i2c_write_nbyteunsigned charsla,unsigned chardata_addr,unsigned charreturn0;//发送数据地址i2c_send_bytedata_addr;ifi2c_rec_ack==0//检测应答信号return0;for;le//连续发送LEN长度的字节数n0;lei2c_send_byte*ptr++;ifi2c_rec_ack==0return0;//发送I2CSTOP信号i2c_stop;return1;KfK,〃*功能从12c总线上器件指定地址接收一个字节的数据unsigned chari2c_read_byteunsigned charsla,unsigned chardata_addrunsigned inttemp;i2c_start;//发送I2C START信号i2c_send_bytesla;//发送从器件写命令ifi2c_rec_ack==0//检测应答信号~return0;i2c_send_bytedata_addr;//发送数据地址ifi2c_rec_ack==0//检测应答信号~return0;i2c__start;//重新发送I2C START信号i2c_send_bytesla10x01;//发送器件从器读命令ifi2c_rec_ack==0//检测应答信号{return0;}temp=i2c_rec_byte;i2c_send_noack;//接收最后一个字节后发送NOACK信i2c_stop;//发送I2CSTOP信号return temp;ti〃*功能从12c总线上器件指定地址接收一个字节的数据i1bit i2c_read_nbyteunsigned charsla,unsigned char*ptr,unsigned data_addr,unsigned charchari2c_start;//发送12C START信号i2c_send_bytesla;//发送从器件写命令ifi2c_rec_ack==0//检测应答信号return0;i2c_send_bytedata_addr;//发送数据地址ifi2c_rec_ack==0//检测应答信号return0;i2c_start;//重新发送I2C START信号i2c_send_bytesla10x01;//发送器件从器读命令//检测应答信号ifi2c_rec_ack==0return0;//连续接收LEN-1长度的字节数for;lenl;len-据*ptr++=i2c_rec_byte;//发送ACK信号i2c_send_ack;//接收最后一个字节*ptr=i2c_rec_byte;//发送NOACK信号i2c_send_noack;//发送I2CSTOP信号i2c_stop;return1;
5.AD模块SPI总线len利用TLC1549实现,TLC1549可以将输入的摹拟量转换成数字量,并且是10位数字量,然后也是利用SPI总线一位一位的发送,因此需要传两字节的数据,高地址中的低两位有效,低地址中的八位都有效,传送过程结合时序图进行编程模块使用的函数是模块驱动程序参考中的函数sbit SCLK=P1A2;sbit DIO=P1A3;sbit ADCS=P1A4;sbit DACS=P1A5;void Before_Once_ADvoid;〃预采集uint adc_1549void;〃读取AD输出的lObit数据
6.DA模块SPI总线利用TLC5615实现的,TLC5615也是利用SPI总线一位一位的传送,并且要求传送的数据是12位,因此需要传两字节的数据,分别放在HIGHD和LOWD中,12位数据是HIGHD中的八位和LOWD中的高四位,但是12为数据中的低两位又是无效的,所以惟独10位有效数字模块使用的函数是模块驱动程序参考中的函数〃函数功能描述驱动TLC5615开始DA转换〃dat为被转换的数字量void tlc5615uint dat;
7.日历芯片PCF8563是低功耗的CMOS实时时钟/日历芯片,它提供一个可编程时钟输出,一个中断输出和掉电检测器,所有的地址和数据通过12C总线接口串行传递每次读写数据后,内嵌的字地址寄存器会自动产生增量按12c总线协议规约PCF8563有惟一的器件地址0A2H因此,可以由CPU把初始化的日历时钟通过总线接口串行传递写入PCF8563,由PCF8563以此为起点自动计时,再通过12c总线串行接口从PCF8563读出内部的日历/时钟这部份主要是在12c总线协议的基础上进行通信,向芯片指定地址写入控制字,写入时间数据或者读出时间数据由于芯片中的实际数据都是以BCD码形式存储,因此通信时需要进行十六进制数和BCD码的互相转换具体设计函数包括向芯片写入时间,从芯片读出时间,码制转换程序代码://8bit十六进制转bed码unsigned charNUM2BCDunsigned charx{return{x/10«4|x%10;//8bit bed码转十六进制unsigned charBCD2NUMunsigned charx returnx»4*10+x0x0f;/*函数说明写入时间秒,分,时,日,星期,月,年,BCD码*/void wt_timeunsigned char*t i2c_write_byte0xA2Qx00Qx00;〃开始计时i2c_write_nbyte0xA2,0x02X7;〃写入时,间读时间*//*void rd_timeunsigned char*time int i;unsigned charaddr=0x02;unsigned chartemp;fori=0;i7;i++temp=i2c_read_byte0xA2,addr;〃去掉无效位〃秒,分ifi==0||i==ltemp=0x7f;ifi==2||i==3〃时,日temp=0x3f;ifi==4〃星期temp=0x07;ifi==5〃月temp=0xlf;time[i]=temp;//Delay_ms50;Delay_us100;addr=addr+l;〃页读须软件累加地址
8.语音芯片这部分直接使用了模块驱动程序参考中的函数,ISD_WR_APC2uchar voiceValue函数可以调节音量,0xa8对应最大音量,Oxaf对应最小音量play_openunsigned intAddST,unsignedint AddEN函数可以根据播放的首尾地址播最不同的音乐
9.库文件定义和使用一个模块的文件包括头文件*.h和源文件*.Co在头文件中进行函数的声明,在对应源文件中将头文件首先包含进来,然后对函数进行具体定义实现使用时用到了某个模块,先将头文件include进来,然后在工程中添加对应的C文件千万不要忽略了头文件中的#ifndef,这是一个很关键的东西比如你有两个C文件,这两个C文件都include了同一个头文件而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突还是把头文件的内容都放在#ifndef和#endif中吧不管你的头文件会不会被多个文件引用,你都要加之这个普通格式是这样的#ifndef标识》#define〈标识〉#endif实验过程:
1.键盘和LCD的测试功能描述初始状态LCD上第一行显示O:get char,第二行显示“l:get decimal”按0进入获取字符并显示的状态,按字符F退出返回初始状态,按1进入获取整数并显示状态整数范围99999,当键入99999时退出返回初始状态主要代码###[lcdtest.c]###void mainvoidunsigned char key,flag;long dec;LCD_lnit;//lcd初始化Keyjnit;LCD_clear;whilelLCD_setcursol0,0;LCD_putsO:get char;LCD_setcursol0,l;LCD_putsl:get decimal;flag=GetChar;ifflag==O||flag==lbreak;LCD_clear;LCD_setcursol0,0;whileliff|==,O,ag{key=GetChar;LCD_putcharkey;ifkey=二Fbreak;〃当按F时跳出ifflag==,l,LCD_setcursol0,0;dec=GetDec;LCD_clear;LCD_putdecdec;ifdec==99999break;〃当输入整数为99999时跳出
2.LCD和LED显示日历功能描述初始状态LCD显示欢迎界面,提示按F键进入,按F后进入提示菜单,按选择程序中默认的日期设定,按1选择手动设定日期,挨次按照提示键入日期日期设定后在LCD上显示全部日期信息,LED上显示时分秒主要代码###[calendar.c]###unsigned charshow
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,OxOO};//led显示数值表unsigned chartime
[7]={0x01};//^,分,时,日,星期,月,年BCD码/*函数说明软件设定时间秒,分,时,日,星期,月,年,BCD码*/void set_timeunsigned char*timeLCD_clear;LCD_setcursol0,0;LCD_putsSet year0^99:;LCD_setcursol0,l;time
[6]=NUM2BCDunsigned charGetDec;LCD_clear;LCD_setcursol0,0;LCD_putsSet month1^12:H;LCD_setcursol0,l;time
[5]=NUM2BCDunsigned charGetDec;LCD_clear;LCD_setcursol0,0;LCD_putsSet day:1;LCD_setcursol0,l;time
[3]=NUM2BCDunsigned charGetDec;LCD_clear;LCD_setcursol0,0;LCD_putsSet weekday仍6:;LCD_setcursol0,l;time
[4]=NUM2BCDunsigned charGetDec;LCD_clear;LCD_setcursol0,0;程序代码〃键盘初始化,将标志位置1;void KeyjnitvoidbKeyllp_Flag=l;〃标志全局变量位置1}〃键盘扫描函数,得到键的行列位置;unsigned charGetScanKeyvoid unsigned char key,i,temp;unsigned charxdata*ptr;for i=l;i0xl0;i«=l〃i的低4位为行数位,行挨次检测循环4次key=Oxff;ptr=0x8fff;*ptr=i;〃取键盘10口的值temp=*ptr;〃屏蔽高四位temp=OxOf;if〃是否有有效键值temp!=0x00key=i«4;〃取行数位的值并将其放入返回值高4位key|=temp;〃列数位的值放入返回值低4位break;〃返回行位高四和列位低四return key;〃取键值,长按无效unsigned charGetKeyvoid unsigned char key,temp;if!bKeyllp_Flag〃判断标志,是0执行/***按键程序执行一次后会将bKeyUp.Flag标志位清零,执行此段程序,长按键无效返回无效值,直至按键无疑返回无效按键值,置“T标志位按键输入恢复有效屏蔽这部份则长按键有效***/key=GetScanKey;ifkey==Oxff〃没有按键,置标志位bKeyUp_Flag=l;LCD_putsSet hour0^23:;LC D_setc ursol0,l;time
[2]=NUM2BCDunsigned charGetDec;LCD_clear;LCD_setcursol0,0;LCD_putsSet minute0^59:;LCD_setcursol0,l;time[l]=NUM2BCDunsigned charGetDec;LCD_clear;LCD_setcursol0,0;LCD_putsSet second0~59:“;LCD_setcursol0,l;time
[0]=NUM2BCDunsigned charGetDec;函数说明软件设定缺省时间秒,分,时,日,星期,月,年,BCD码*/〃将2022年6月13日星期一下午3点15点59分30秒的时间写入PCF8563voidset_default_timeunsigned char*t{一一t
[0]=0x30;t[l]=0x59;t
[2]=0xl5;t
[3]=0xl3;t
[4]=0x01;t
[5]=0x06;t
[6]=0xll;//--------------日历显示-----------------void CalendarDispunsigned char*time//LCD显示----LCD_setcursolO O;z//yearLCD_putchar2;LCD_putcharO;LCD_putcharKey_ASC2time
[6]»40x0f;LCD_putcharKey_ASC2time
[6]0x0f;LCD_putchar-;//monthLCD_putcharKey_ASC2time
[5]»40x0f;LCD_putcharKey_ASC2time
[5]0x0f;LCD_putcharC-1;//day:「八期jeqD psuSisunpiOAUieiU piOAI11ffPU3一坐售Q31//fOZsnj-Ae|9a//f/v\oqsAe|dsipMO剪0]3W!k⑹Moqs力
[0]3W!4[t]Moqs Joxo心
[1]3叫4⑵/v\oqs•t7«[T]9Lun=[s]/v\oqs Joxoe⑵3W㈤Moqs^«
[2]3tU!l=[S]Moqsf0=
[9]/v\oqs=[£]/v\oqs——当智向--------------------------------------------------------------//pua一坐售QD1-------------//,JOXoe[o]3WR乙3SV一八3X」eq31nd一qi,JOx公
[0]3山甲5\/一人31」叫”nd-si puooas//CipincT-si,期09任]3山!烟svFsx」叫“nd-si!0乂0公17
[1]3山!1乙DSV一八3»」eip ind-Q Hajnuiiu//r,」eip】nd-si3[,JOxog
[1]WR DSV一人3」eipind-a1!JOX公[乙]3WR[sv一八3»」eq31nd—a1」noq〃[0|os」n”3S-si^eajqff.jesJsind-Q3-]9aseo^esjqft.jJdJsind-aDi ssseo^esjqft^qijsind-aD1t73sB3,eaq4P3/V\“s】nd—si£sseoCOINf|eajqf anisind-sseo1I IIQDI Tf|e9jqf uo|Al swcl—sseoII II,咨」q4“uns“sind-si osseo[tz]9iU!JqDi!/v\s人ep|33M//Q」eq“nd-CDi;U0X0^[£]9^n^sV-A9|jeq3wd—Q31:◎0£[£]3W!1《制一人3|」四“nLsiLCDJnit;//lcd初始化Key_lnit;LCD_clear;LCD_setcursol0,0;LCD_puts----Calendar----;LCD_setcursol0,l;LCD_putspress Fto start;whileGetChar!=F;LCD_clear;LCD_setcursol0,0;LCD_putsO autoset;LCD_setcursol0,l;LCD_putsl manualset;whilelkey=GetChar;ifkey==,Oset_default_timetime;break;ifkey==,lset_timetime;break;wt_timetime;LCD_clear;whilelrd_timetime;CalendarDisptime;ifGetKey!=Oxffbreak;〃当按任意键时跳出KK//不不不不不不不不不ain end不不不不不不不不不不不不不不不可不
3.D/A通道锯齿波发生器功能描述初始状态LCD显示界面,按1产生方波,按2产生锯齿波调节示波器扫描周期和幅值可以观察到DA的输出端口的输出的波形主要代码###[da.c]###void mainvoiduintdat=OxOOOO;uchar key;LCDJnit;LCD_setcursolO O;zLCD_putslsquareH;LCD_setcu rsol0,l;LCD_puts2sawtooth;whilel key=GetChar;ifkey==l||key==2break;LCD_clear;whilelifkey二二T〃方波LCD_setcursol0,0;LCD_putssquare;tlc56150;Delay_uslOO;tlc5615512;Delay_uslOO;ifkey==2〃锯齿波LCD_setcursol0,0;LCD_putssawtooth;ifdat512dat=dat+10;〃步进elsedat=O;tlc5615dat;Delay_us⑸;ifGetKey!=Oxff{break;}
4.A/D通道读取电压显示在LCD上功能描述将J3口的1,2用导线短接,调节电位器R20,使电压从0~5V改变初始状态下LCD显示界面,按1进行均值滤波,按2键进行中值滤波,按3键进行滑动平均滤波假设采样数据为N个,均值滤波是将N个数据求取平均值,中值滤波是先将N个数据排序,然后取中值,滑动平均滤波是每次用新采样的m个数据替换最老的m个数据mN,然后将N个数据进行均值滤波每次按一个键更新一次电压显示值,按下键返回主界面主要代码###[ad.c]####define NUM4〃滤波样本数据个数〃函数功能描述;预先采集;void Before_Once_ADvoid一uchar i;SCLK=DIO=0;ADCS=0;〃开启控制电路,使能DATA OUT和I/O CLOCKfori=l;i=10;i++SCLK=1;_nopj;SCLK=O-_nopj;ADCS=1;Delay_us25;〃两次转换间隔大于21us〃排序函数void sortuint*Arrayuchar ij;uint temp;fori=0;iNUM-l;i++forj=i+l;jN UM;j++ifArray[i]Array[j]temp=Array[i];Array[i]=Array[j];Array[j]=temp;}〃平均值滤波uint ad_FilterAverageuint*Arrayuchar i;uint sum=O;for i=O;iNUM;i++sum+=Array[i];return sum/NUM;〃中值滤波uint ad_FilterMediauint*ArraysortArray;return Array[NUI\/l/2+l];〃滑动平均滤波uint ad_FilterSlideuint*Array{uchar i;fori=0;iNUM-l;i++Array[i]=Array[i+l];Array[NUM-l]=adc_1549;return ad_FilterAverageArray;}void mainvoiduintad,da;uchar temp,i,key;uint ArrayfNUM];float fad;uint lad;LCDJnit;LCD_setcursol0,0;LCD_putslaverage2media;LCD_setcursol0,l;LCD_puts3slide;whilelkey=GetChar;ifkey==l||key==2|||key==l3,break;}Before_Once_AD;fori=0;iNUM;i++Array[i]=adc_1549;LCD_clear;whilel{Before_Once_AD;switch keycase「:〃平均值滤波fori=0;iNUM;i++Array[i]=adc_1549;ad=ad_FilterAverageArray;LCD_setcursol0,0;LCD_putsAverage filter;break;case2:〃中值滤波fori=0;iNUM;i++Array[i]=adc_1549;ad=ad_FilterMediaArray;LCD_setcursol0,0;LCD_putsMedium filter;break;case3:〃滑动平均滤波ad=ad_FilterSlideArray;LCD_setcursol0,0;LCD_putsSlide filter;break;fad=floatad/1024Q*5・0;〃转化为摹拟电压值lad=uintfad*10000;//放大LCD_setcu rsol0,l;LCD_putdeclad;ifGetChar==,F,break;
5.语音芯片模块功能描述按0〜B键选择不同声音播放,按C键减音量,按D键加音量主要代码###[voice.c]###//--------------主函数,可选择录音,调节音量----------------------------------------------void mainvoiduchar key=Oxff;LCD_lnit;ISD_lnit;ISD_WR_APC2voice;whilel{LCD_clear;LCD_setcursol0,0;LCD_putsvoicel-13;LCD_setcursol0,l;LCD_putschvo:downl3/upl4;select_voicekey;key=Oxff;whilekey==Oxff key=GetKey;〃根据键值选择播放的音乐void select__voiceuchar keyswitchkeycase13:changevoice0;〃调低音量LCD_clear;LCD_setcursol0,0;LCD_putsvoice down;break;case14:changevoice⑴;〃调高音量LCD_clear;LCD_setcursol0,0;LCD_putsvoice up;break;case15:break;default:play_openAudio_Addr[keyLAudio_Addr[key+l];break;//选择歌曲〃音量调节函数void changevoiceucharflagif flag==0voice0xaf〃调小音量voice++;else ifflag==lvoice0xa8〃调大音量voice-;ISD_WR_APC2voice;
五、心得体味:本次实验主要学习了一些单片机与CPU与外设通信和控制协议,包括12c总线,SPI总线,DS18B20的单总线通信等通过实验,让我认识到实验板的强大功能,也让我看到了单片机等嵌入式系统的广泛应用最后感谢老师在实验中的耐心指导和匡助!else〃保持按键return Oxff;〃因为Oxff大于15,故为无效键值,实现长按键无效key=GetScanKey;ifkey==Oxff〃没有按键return key;else〃有按键有效temp=key;〃取键值Delay_ms20;〃延时20ms消抖key=GetSca nKey;〃键盘扫描ifkey!=temp〃判断两次键值是否相同,排除干扰信号影响确认有效信号key=Oxff;return key;else〃取键值/*这部份主要作用是软件抗干扰*/temp=Key_Value_Table[key»4];〃见说明/*行值有效位键盘的4个行SEL返回的值含有的有效位叮有且惟独一位键值才有效否则返回无效键值*/if temp==0xffkey=Oxff;return key;temp=Key_Value_Table[keyOxOf];/*列值有效位键盘的4个列RL返回的值含有的有效位1”有且惟独一位键值才有效否则返回无效键值*/if temp==0xffkey=Oxff;return key;key=Key_Value_Table[key»4]*4+Key_Value_Table[key0x0f];〃行对应的中间值的四倍与列7寸应而中间值之和即为按键翥号,15/*行列组合后的值大于15无效*/if key15key=Oxff;return key;bKeyUp_Flag=O;return key;〃获得键盘输入字符int GetCharvoidunsigned charkey=0xff;whilekey==Oxffkey=GetKey;/*wait inputfix*/return intkey_arrenge[key];/*change toASCII codeand return*/〃获得键盘输入整数long GetDecvoidlongout_dec=0;/*resultdecimal number数值范围0~99999*/unsigned charij;/*variable forcharacter countinttemp=0;int key;fori=0;i6;key=GetChar;ifkey=,9key=0/*获取键值O—9*/temp=key-O;/*获取数值0-9*/out_dec=out_dec*10+longtemp;ifout_dec==0continue;/*首位数据输入为时,显示不变*/i++;LCD_putcharkey;continue;/*显示当前输入的数据*/if,E,==key/*当前输入清零*//*清显示区*/back_cursoli;out_dec=0;forj=0;ji;j++LCD_putcharC;back_cursoli;continue;/*清显示区*/ifF==key ENTER键,数值确认*/return out_dec;ifC==key/*撤销最近一个输入数字*/out_dec=out_dec/10;back_cursoll;LCD_putcharC;back_cursoll;continue;
2.LED模块通过送字形码和字位码可以点亮对应的一个8段LEDo8个LED的同时显示通过循环扫描显示实现,即每次在一个LED上显示设定的数字,延时显示一段时间延时越长,亮度越好,然后切换显示下一个,挨次轮换程序代码unsigned charLed_table
[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7t0x6t0x77,0x76,0x39,0x56,0x79,0x71;void Delay_uslint t一whilet-=0;〃函数功能描述给显示数组赋初始值;void Led_lnitunsigned char*showunsigned chari;for i=0;i8;i++〃在此处给显示数组赋值*show=0x00;show++;〃函数功能描述在LED上显示;void displayunsigned char*show unsigned chari=l,j;unsigned charxdata*ptr;for j=0;j8;j++〃八个数码管全部显示ptr=0x8fff;〃段选地址*ptr=i;ptr=0x9fff;〃位选地址〃在此给*ptr赋值送字形码*ptr=Led_table[show[j]];Delay_usl30;*ptr=0x00;下一位〃数字转led字形码unsigned charasc2ledunsigned chara return*Led_table+a;}
3.LCD显不模块设计思路LCD的显示通过给LCD写命令和数据实现写数据与写指令时各控制引脚的电平不同,对应了不同的地址先构造写数据和写命令函数与硬件相关操作,已经检测LCD是否忙的函数当处于忙状态时不能写数据,否则硬件会工作不正常,在此接口的基础上构造库与硬件无关操作,通过调用写数据和写命令函数实现,实现各种不同的功能,包括初始化设定工作方式,显示字符,显示字符串,显示数字0~99999,清屏,设定光标的位置等这里的显示字符,显示整数和键盘检测模块的读入字符,读入整数对应起来,可以合作使用使用时先调用初始化函数初始化LCD,设定工作方式,然后可以调用不同的函数实现不同的显示程序代码/*=====define variable=====*/unsigned charcursol_x;/*cursor positionhorizontal*/unsigned charcursol_y;/*cursor positonvertical*/unsignedcharxdata*ptr;〃指向XDATA的指针访问片外地址unsignedcharcodeASC2_Value_Table
[16]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};〃「二「二二二向1602指令寄存器写指令==========void WriteWunsignedchar aptr=OxAFFO;//RS=O,R/W=0*ptr=a;〃============向1602指令寄存器写指数据============void WriteDunsignedcharkey_asc2CheckBF;ptr=0xAF02;*ptr=key_asc2;〃二二二二二二二二二检查忙标志位BF=============void CheckBFvoidunsigned inti;whilel ptr=OxAFFl;//RS=O,R/W=l i=*ptr;i=0x80;ifi==0break;//==========LCD初始化二二二二二二二二二二void LCDJnitvoid-CheckBF;WriteW0x38;CheckBF;WriteW0x01;//Clear display清显示CheckBF;WriteW0x06;//Entry modeset:l/D=l,S=O[l:lncrease,D:Decline,S:Shift]CheckBF;WriteWOxOF;//Dislpay on/off controlD=l,C=l,B=l[D:Display,C:Cursor B:Blink]CheckBF;/WriteW0x80;//Dislpay on/off controlD=0,C=0B=0[D:Display,C:Cursor,B:Blink]/〃二二二二二设定光标所在位置==========voidLCD_setcursolunsigned charx,unsignedchary/*cursor positionhorizontal*/cursol_x=x;/*cursor positonvertical*/cursol_y=y;/*wait LCDprocess*/CheckBF;|y*0x40+x;/*address ofthe secondline0x40-0x4fWriteW0x80〃二二二二二二后移光标二二二二二二二voidmove_cursolvoid if++cursol_xOxOf{/*move cursorto right,if getto endofthe line*/cursol_x=0;/*move to begin ofthe line*/if++cursol_y=2{/*return,if overthe secondline*/cursol_y=0;/*return tobegin ofthe line*/}LCD_setcursolcursol_x,cursol_y;/*set cursor*/voidback_cursolint i〃二二二二二二前移光标二二二二二二二cursol_x-=i;LCD_setcursolcursol_x,cursol_y;/*set cursor*/void LCD_clearvoid}一〃======清屏=======CheckBF;/*wait LCDprocess*/WriteWOxOl;/*clear display*/voidLCD_putcharint c〃二二二二二二写字符二二二二二二二ifc==\n||c==\r/*line feedcode*/cursol_x=0;cursol_y A=1;LCD_setcursolcursol_x,cursol_y;/*set cursor*/CheckBF;/*wait LCDprocess*/WriteDc;/*write Data-Register*/CheckBF;/*wait LCDprocess*/move_cursol;/*move cursorposition*/〃二二二二二二二二写字符串========voidLCD_putsconst unsignedchar*s for;\0!=*s;s++{/*loop beforenull code*/LCD_putchar*s;/*display characteron LCD〃========写整数======:可打印的数据小于99999*/voidLCD_putdeclong declong num;/*number tobe displayed*/inti;/*loop counter*/unsignedcharstr_buf
[5];/*buffer fordata display*/num=dec;/*save numbertobedisplayed*/fori=0;num!=0;i++/*confirm digit*/str_buf[i]=num%10;/*get everydigit numberand saveinbuffer*/num=num/10;ifi==0/*if numberis0*/LCD_putcharO;/*display Oin LCD*/一else/*if numberis not0*/for-i;i=0;i-/*loop timesof digits*/LCD_putcharstr_buf[i]+0;/*a代er transferee!into ASCIIcode*/}/*display inLCD*/〃十六进制码转换为ascii码unsignedcharKey_ASC2unsignedcharkey。