《新概1单片机C语言教程例程》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
目录例2.2.1编写程序,点亮第一个发光二极管(part2_l.cP27)-4-例2.5.1利用for语句延时特性,编写第一个发光二极管以间隔1S亮灭闪动的程序(part2_3.cP42)-5-例2.6.1编写程序使第一个发光二极管以间隔500ms亮灭闪动。(part2.4.cP48)5-例2.7.1编写程序使第一个二极管以亮200ms、灭800ms的方式闪动。(part2_5.cP49)-6-例2.8.3利用C51自带库一crol_(),以间隔500ms,实现流水灯程序(part2_6.cP53)-6例3.2.1编写程序使第一个数码管显示8(part2,1_.lcP59)-7-例3.2.2让实验板上6个数码管同时点亮,依次显示0到F,时间间隔为0.5ms,循环下去。(part2.1_2.cP61)-8-例3.3.1第一个数码管显示1,时间为0.5s,然后关闭它,立即让第二个数码管显示2,时间为0.5s,在关闭它……一直到最后ー个数码管显示6,时间同样为0.5s,关闭它之后再回来显示第一个数码管,一直循环下去。(part2.1_3.cP62)-9-例3.5.1利用定时器。工作方式1,在实验板上实现第一个发光管以!s亮灭闪烁。(part2.1.4.cP74)-11-例3.5.2用定时器〇的方式1实现第一个发光二极管以200ms间隔闪烁,用定时器1的方式1实现数码管前两位59s循环计时。(part2.1_5.cP75)-12-例4.1.1用数码管前两位显示ー个十进制数,变化范围为〇〇〜59,开始时显示00,每按下S2键一次,数值加1;每按下S3健一次,数值减1;每按下S4健一次,数值归零:按下S5键一次,利用定时器功能使数值开始臼动每秒加1,再次按下S5键,数值停止加1,保持显示原数。(part2.2_l.cP82)-14-例4.2.1实验班上电时,数码管不显示,顺序按下矩阵键盘后,数码管上依次显示。〜f,六个数码管同时静态显示即可。(part2.2_2.cP87)-17-例5.3.1用单片机控制ADC0804进行数模转换,当拧动实验板上A/D旁边的电位时,在数码管的前三位以十进制方式显示出A/D转换后的数字量(8位A/D转换后数值在〇〜255变化)。(part2.3_l.cP107)-21-例5.5.1用单片机控制DAC0832芯片输出电流,让发光二级管D12由灭均匀变到最亮,再由
1最亮均匀熄灭。在最亮和最暗时使用蜂鸣器分别警报一声,完成整个周期时间控制在5s左右,循环变化。(part2.3一2.cP121)-23-例6.5.1在上位机上用串口调试助手发送ー个字符x,单片机收到字符后返回给上位机“IgetX”,串口波特率设为9600bps。(part2.4_l.cPl37)-25-例6.6.1单片机上电后等待从上位机串口发来的命令,同时在数码管的前三位以十进制方式显示A/D采集的数值,在未收到上位机发送来的后动A/D转换命令之前数码管始终显示000。当收到上位机以十六进制发送来的01后,向上位机发送字符串“Turnonad!”同时间隔1s读取一次A/D的值,然后把A/D采集回来的8位二进制转换成十进制表示的实际电压浮点数,并且从串口发送给上位机,形式如“Thevoltageis3.398438V”,发送周期也是一秒一次,同时在数码管上也要每秒刷新现实的数值。当收到上位机以十六进制发送过来的02后,向上位机发送字符串“Turnoffad!”,然后停止发送电压值,数码管上显示上次结束时保持的值。当收到上位机发来的其他任何数时,向上位机发送字符串“Error!”。.....-27-例7.2.1实现!602液晶的第一行显示“ILOVEMCU!”,在第二行显示WWW.TXMCU.COMo-31-例?.2.2实现!602第一行从左侧移入“Helloeveryone!M同时第二行从右侧移入"Welcometohere!w,移入速度自定,然后停留在屏幕上。(part2.5_2.cP154)-33-例7.3.1实现12232液晶的第一行显示"ILOVEMCU!”,第二行显示"我爱单片机”。(part2.5_3.cP160)-34-例7.3.2实现12232液晶第,一行从右侧移入“Helloeveryone!”,同n寸第二行从右侧移入“欢迎大家来学习!”移入速度自定,最后停留在屏幕上。(part2.5一4.cP163)-37-例7.4.1实现在12864液晶上第一行显示“0123456789”,并且让每一位数字随机变化,第二行显示“www.txmcu.com”,第三行显示“天祥电子”,第四行对应第三行显示出下划线。(part2.5_5.cPl73)-40-知识点:生成随机数(part2.5_512232suiji.cP176)-44-例8.3.1利用定时器产生一个。〜99秒变化的秒表,并且显示在数码管上,每过一秒将这个变化的数写入板上AT24co2内部。当关闭实验板电源,并再次打开实验板电源时,单片机先从AT24C02中将原来写入的数读取出来,接着此数继续变化并显示在数码管上。(part2.6_l.cP188)-48-例10.1.1利用定时器〇工作方式〇,在实验板上实现第一个发光管以1s亮灭闪烁。(part3.1.1.cP203)-53-例10.2.1利用定时器。工作方式2,在实验板上实现第一个发光管以!s亮灭闪烁。(part3.1.2.cP204)-54-例10.3.1利用定时器工作方式3,在实验板上实现:用TL0计数器对应的8位定时器实现第一个发光管以1s亮灭闪烁,用THO计数器对应的8位定时器实现第二个发光管以0.5s亮灭闪烁。(part3.1.3.cP206)-54-
2例10.5.1利用计数器。工作方式1,在实验板上实现:用ー根导线一端连接GND引脚,另一端去接触T0(P3.4)引脚,每接触一下,计数器计ー次数,将所计的数值实时显示在数码管的前两位,计满100时清〇,再从头计起。(part3.1.4.cP214)-55-例11.1.1设置单片机串行口的工作模式〇,间隔循环发送十六进制数。xAA,然后用双路示波器观察P3.。和P3.1口波形。(-58-例11.3.1用交叉串口线连接两块实验板,或直接用短线交叉线连接连个单片机的P3.0和P3.1ロ(共地)。在ー块板上编写矩阵键盘扫描程序,当扫描到有键按下时,将键值通过串口发送出去,另ー块板上单片机收到串口发送来的键值后,将对应键值以0-F方式显示在数码管上。-60-例11.4.1程序分为主机程序和从机程序,约定一次传送的数据为16B,以。2H地址的从机为例。(图11.4.2为多机通信主机程序流程图)-65-图11.4.3为多机通信从机程序流程图。-68-从机程序代码:(part3.2.6.cP234)-68-例12.8.I指针使用例程:(point.cP264)-71-例13.1.1编写程序实现:开启两个外部中断,设置低电平触发中断,用定时器计数并且显示在数码管的前两位,当计数到5时,使单片机进入空闲(休眠)模式,同时关闭定时器,当单片机响应外部中断后,从空闲(休眠)模式返回,同时开启定时器。(-72-例13.2.1实验板上实现如下描述:程序启动后设定看门狗溢出时间为2s,然后点亮第ー个发光二极管,稍延时一会,然后熄灭发光二极管,使程序进入等待死循环状态,并且在死循环中大约每隔1s喂狗一次,看程序运行是否正常。-74-例13.6.1.在实验板上实现:操作STC单片机自带的E2PR0M,存储ー组按秒递增的两位数据,并且将数据实时显示在数码管上,数据每变化一次就往E2PROM中写入一次,当关闭实验板电源并再次开启电源时,从E2PROM中读取先前存储的数据,接着递增显示。-7コー例13.7.1STC89LE516AD/X2系列单片机的A/D转换功能。时钟11.0592MHz,转换结果以16进制形式输出到串行口,可以用串行口调试程序,观察输出结果(本代码摘自宏晶科技芯片手册,经作者调试可正常运行)。-80-例13.8.1给出ー个STC12c5412AD应用的参考程序。(part3.4.6.cP287)-82-程序14.3.1利用51单片机的定时器设计一个时钟。-89-程序15.5.1使用DS12c887时钟芯片设计高精度时钟。-97-程序16.3.1使用TX-1C实验板上的DS18B20温度传感器设计温控系统C语言源代码(part4.3P349)-108-程序17.3.1太阳能充/放电控制器C语言源代码-114-
3ISD400X系列语音芯片C语言参考程序:-134-例21.1.1使用TX-1C实验板上两个独立按键调节直流电机的转速,同时在实验板的数码管上象征性的显示相应的转速值。通过控制单片机输出不同占空比的PWM信号来控制直流电机的转速(感性认识)。(part5.3P434)-138-例21.2.1步进电机应用C语言程序设计(Part3.2P444)-142-例21.3.1陀机应用c语言程序设计实例:开机时舵机角度自动转为〇度,通过实验板上的独立按键调节舵机的角度转动,并且在实验板数码管上显示相应的角度。本例仅演示5个角度的控制,若想实现任意角度控制请大家自行编程实验。程序代码如下:(pah5.3P453)-145-〃调节舵机使之转动5个角度04590135180PWM信号周期为20ms,-145-〃控制高电平的持续时间即可控制舵机停止制动的角度,0.5ms-0度1-451.5-902-1352.5-180-145-〃程序流程是:开机时舵机角度自动转为〇度,按下P3.7则转到45度,以后就根据两个按键的按下而转动-145-例2.2.1编写程序,点亮第一个发光二极管(part2_l.cP27)#include
4sbitledl=PlA0;〃声明单片机Plロ的第一位uinti,j;voidmain()〃主函数(while(l)〃大循环{ledl=O;/・点亮第一个发光二极管・/for(i=l;i>0;i—)〃延时for(j=110;j>0;j-);led1=1;/*关闭第一个发光二极管・/for(i=1000;i>0;i-)〃延时for(j=110j>0;j-);}例2.6.1编写程序使第一个发光二极管以间隔500ms亮灭闪动。(part2_4.cP48)#include
5voiddelayls()(uinti,j;for(i=500;i>0;i-)for(j=110;j>0;j-);〃子函数体例2.7.1编写程序使第一个二极管以亮200ms、灭800ms的方式闪动。(part2_5.cP49)#include
6aa=Oxfe;while(l){Pl=aa;delayms(500);aa=_crol_(aa,l);))voiddelayms(uintxms)(uinti,j;fbr(i=xms;i>O;i-)for(j=110;j>0;j-);//赋初值11111110〃大循环〃延时500毫秒〃将aa循环左移1位后再赋给aa//i=xms即延时约xms毫秒例3.2.1编写程序使第一个数码管显示8(part2.l..lcP59)#include
7voidmain()(wela=l;〃打开U2锁存器P0=0xFE;〃送入位选信号wela=0;〃关闭U2锁存器dula=l;〃打开U1锁存器P0=0x7F;〃送入段选信号dula=0;〃关闭U2锁存器while(l);}〃程序停止到这里例3.2.2让实验板上6个数码管同时点亮,依次显示0到F,时间间隔为0.5ms,循环下去。(part2.・一2.cP61)#include
8#include
9P0=table⑵;〃送段选数据dula=0;P0=0xff;〃送位选数据前关闭所有显示,防止打开位选锁存时wela=l;〃原来段选数据通过位选锁存器造成混乱P0=0xfd;〃送位选数据wela=0;delayms(500);〃延时dula=l;P0=lable[3];〃送段选数据dula=0;P0=0xff;〃送位选数据前关闭所有显示,防止打开位选锁存时wela=l;〃原来段选数据通过位选锁存器造成混乱P0=0xfb;,,/送位选数据wela=0;delayms(500);〃延时dula=l;P0=table(4];〃送段选数据dula=0;P0=0xff;〃送位选数据前关闭所有显示,防止打开位选锁存时wela=l;〃原来段选数据通过位选锁存器造成混乱P0=0xf7;〃送位选数据wela=0;delayms(500);〃延时dula=l;P0=table[5];〃送段选数据dula=0;P0=0xff;〃送位选数据前关闭所有显示,防止打开位选锁存时wela=l;〃原来段选数据通过位选锁存器造成混乱P0=0xef;〃送位选数据wela=0;delayms(500);〃延时dula=l;P0=table[6];〃送段选数据dula=0;P0=0xff;〃送位选数据前关闭所有显示,防止打开位选锁存时wela=l;〃原来段选数据通过位选锁存器造成混乱P0=0xdf;〃送位选数据wela=0;delayms(500);〃延时voiddelayms(uintxms)(uintij;
10for(i=xms;i>0;i-)//i=xms即延时约xms毫秒for(j=110;j>0;j-):例351利用定时器。工作方式1,在实验板上实现第一个发光管以1s亮灭闪烁。(part2.14.cP74)#include
11sbitwela=P2A7;〃申明U2锁存器的锁存端sbitledl=PlAO;uncharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71);voiddelayms(uint);voiddisplay(uchar,uchar);ucharnum,numl,num2,shi,ge;voidmain()(TMOD=0xll;〃设置定时器。为工作方式1(MIMO为11)TH0=(65536-45872)/256;〃装初值11.0592M晶振定时50ms数为45872TL0=(65536-45872)%256;TH1=(65536-45872)/256;〃装初值!1,0592M晶振定时50ms数为45872TLl=(65536-45872)%256;EA=1;〃开总中断ETO=1;〃开定时器〇中断ET1=1;〃开定时器1中断TRO=1;/Z启动定时器〇TR1=1;/Z启动定时器1while(l);〃程序停止在这里等待中断中断发生(display(shi,ge);voiddisplay(ucharshi,ucharge)〃显示子函数(dula=l;PO=table[shi];〃送段选数据dula=O;PO=Oxff;〃送位选数据前关闭所有显示,防止打开位选锁存时wela=l;〃原来段选数据通过位选锁存器造成混乱PO=Oxfe;〃送位选数据wela=O;delayms⑸;〃延时dula=l;PO=table|ge上〃送段选数据dula=O;PO=OxffJ〃送位选数据前关闭所有显示,防止打开位选锁存时wela=li〃原来段选数据通过位选锁存器造成混乱PO=Oxfd;〃送位选数据wela=O;delayms⑸;〃延时
12voiddelayms(uintxms)(uintij;for(i=xms;i>0;i—)//i=xms即延时约xms亳秒for(j=110;j>0;j-);voidT0__time()interrupt1(TH0=(65536-45872)/256;〃市装初值TL0=(65536-45872)%256;num++;if(numl==4)〃如果到了4次,说明200ms时间到(num1=0;〃然后把numl清〇重新再计4次led1=~led1;〃让发光管状态取反voidTl_time()interrupt3(TH1=(65536-45872)/256;〃重装初值TL1=(65536-45872)%256;num2-H-;if(num2==20)〃如果到了20次,说明1秒刷新时间到(num2=0;〃然后把num2清0重新再计4次num++;if(num=60)〃这个数用来送数码管显示,到60后归〇num=0;shi=num/10;ge=num%10;〃把ー个2位数分离后分别送数码管显示〃十位和个位)
13例4.1.1用数码管前两位显示ー个十进制数,变化范围为00-59,开始时显示00,每按下S2键一次,数值加1;每按下S3键一次,数值减1;每按下S4键一次,数值归零;按下S5键一次,利用定时器功能使数值开始自动每秒加1,再次按下S5键,数值停止加1,保持显示原数。(part2.2_l.cP82)#include
14P0=0xfd;wela=0;delayms(5);)voiddelayms(uintxms)(uinti,j;for(i=xms;i>0;i—)//i=xms即延时约xms毫秒for0=HO;j>O;j-);)voidinit()〃初始化函数(TMOD=0x01;〃设置定时器〇为工作方式1(00000001)TH0=(6553845872)/256,装初值50ms一次中断TL0=(65536-45872)%256;EA=1;〃开总中断ET0=l;〃开定时器〇中断)voidkeyscan()(if(keyl=O)delayms(lO);if(keyl==O)(num++;if(num=60)〃当到60时重新归〇num=O;while(!key1);〃等待按键释放))if(key2=0)(delayms(lO);if(key2==0)(if(num=O)〃当到〇时重新归60num=60;num—;while(!key2);)}if(key3=0){delayms(lO);if(key3=0)(num=0;〃清0while(!key3);}}if(key4=0)(
15delayms(lO);if(key4=0)(while(!key4);TRO=~TRO;〃启动或停止定时器0))}voidmain()(init();〃初始化函数while(l)keyscan();display(num);})voidT0_time()interrupt1(TH0=(65536-45872)/256;〃重装初值TL0=(65536-45872)%256;numtO++;if(numt0==20)〃如果到了20次,说明1秒时间到(numt0=0;〃然后把num清〇重新再计20次num++;if(num==60)num=0;})例421实验班上电时,数码管不显示,顺序按下矩阵键盘后,数码管上依次显示〇〜F,六个数码管同时静态显示即可。(part2.2_2.cP87)#include
16for(j=110;j>0;j-);}voiddisplay(ucharnum){P0=table[num];〃显示函数只送段选数据dula=l;dula=O;)voidmatrixkeyscan()(uchartemp,key;P3=Oxfe;temp=P3;temp=temp&OxfO;if(temp!=OxfO){delayms(lO);temp=P3;temp=temp&Oxf();if(temp!=OxfO)(temp=P3;switch(temp)(caseOxee:key=O;break;caseOxde:key=l;break;caseOxbe:key=2;break;case0x7e:key=3;break;}while(temp!=OxfO){temp=P3;temp=temp&OxfO;)display(key);})P3=Oxfd;temp=P3;temp=temp&OxfO;
17if(temp!=OxfO)delayms(lO);temp=P3;temp=temp&OxfO;if(temp!=OxfO){temp二P3;switch(temp)(caseOxed:key=4;break;caseOxdd:key=5;break;caseOxbd:key=6;break;case0x7d:key=7;break;)while(temp!=OxfO)(temp=P3;temp=temp&OxfO;)display(key);))P3=Oxfb;temp=P3;temp=temp&OxfO;if(temp!=OxfO)(delayms(lO);temp=P3;temp=temp&OxfO;if(temp!=OxfO){temp=P3;switch(temp)(caseOxeb:key=8;break;caseOxdb:key=9;break;
18caseOxbb:key=10;break;case0x7b:key=11;break;)while(temp!=OxfO){temp=P3;temp=temp&OxfO;)display(key);})P3=0xf7;temp=P3;temp=temp&OxfO;if(temp!=OxfO)(delayms(lO);temp=P3;temp=temp&OxfO;if(temp!=OxfO)(temp=P3;switch(temp)(case0xe7:key=12;break;caseOxd7:key=13;break;caseOxb7:key=14;break;case0x77:key=15;break;)while(temp!=OxfO)(temp=P3;temp=temp&OxfO;}display(key);
19voidmain()(P0=0;〃关闭所有数码管段选dula=l;dula=0;P0=0xc0;〃位选中所有数码管wela=l;wela=0;while(l){matrixkeyscan();〃不停调用键盘扫描程序例5.3.1用单片机控制ADC0804进行数模转换,当拧动实验板上A/D旁边的电位时,在数码管的前三位以十进制方式显示出A/D转换后的数字量(8位A/D转换后数值在0〜255变化)。(part2.3_l.cP107)#include
20〃申明U2锁存器的锁存端〃定义AD的WR端口〃定义AD的RD端口sbitwela=P2A7;sbitadwr=P3A6;sbitadrd=P3A7;ucharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71);voiddelayms(uintxms)uinti,j;//i=xms即延时约xms毫秒fbr(i=xms;i>O;i—)for(j=l10;j>0;j—);voiddisplay(ucharbai,ucharshi,ucharge)〃显示子函数(dula=l;PO=table[bai|;〃送段选数据dula=0;PO=OxffJ〃送位选数据前关闭所有显示,防止打开位选锁存时wela=l;〃原来段选数据通过位选锁存器造成混乱P0=0x7e;〃送位选数据wela=0;delayms(5);〃延时dula=l;PO=table[shi];dula=0;PO=Oxff;wela=l;P0=0x7d;weia=0;delayms(5);dula=l;PO=table[ge];dula=0;P0=0xff;wela=l;P0=0x7b;wela=0;delayms(5);voidmain()//主程序uchara,Al,A2,A3,adval;wela=l;P0=0x7f;〃置CSAD为0,选通ADCS以后不必再管ADCSwela=0;whiled){
21adwr=1;_nop_();adwr=0;〃启动AD转换_nop_();adwr=l;for(a=10;a>0;a-)//TX-IC实验板AD工作频率较低,所以启动转换后要多留点时间用来转换{〃这里把显示部分放这里的原因也是为了延长转换时间display(A1,A2,A3);Pl=Oxff;〃读取Pl口之前先给其写全!adrd=1;〃选通ADCS一nop_();adrd=0;//AD读使能_nop_();adval=Pl;//AD数据读取赋给P1ロadrd=1;Al=adval/100;〃分出百,十,和个位A2=adval%100/10;A3=adval%10;)例5.5.1用单片机控制DAC0832芯片输出电流,让发光二级管D12由灭均匀变到最亮,再由最亮均匀熄灭。在最亮和最暗时使用蜂鸣器分别警报一声,完成整个周期时间控制在5s左右,循环变化。(part2.3_2.cP121)
22#include
23例6.5.1在上位机上用串口调试助手发送ー个字符X,单片机收到字符后返回给上位机"IgetX”,串口波特率设为9600bpSo(part2.4_l.cP137)#include
24voidser()interrupt4RI=0;a=SBUF;flag=l;例661单片机上电后等待从上位机串口发来的命令,同时在数码管的前三位以十进制方式显示A/D采集的数值,在未收到上位机发送来的启动A/D转换命令之前数码管始终显示000。当收到上位机以十六进制发送来的01后,向上位机发送字符串"Turnonad!”同时间隔1s读取一次A/D的值,然后把A/D采集回来的8位二进制转换成十进制表示的实际电压浮点数,并且从串口发送给上位机,形式如“Thevoltageis3.398438VW,发送周期也是一秒一次,同时在数码管上也要每秒刷新现实的数值。当收到上位机以十六进制发送过来的02后,向上位机发送字符串“Turnoffad!”,然后停止发送电压值,数码管上显示上次结束时保持的值。当收到上位机发来的其他任何数时,向上位机发送字符串Error!”。(part2.4_2.cP140)#include
250x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71);voiddelayms(uintxms)(uinti,j;for(i=xms;i>0;i—)//i=xms即延时约xms毫秒for(j=110;j>0;j-);1voidinit()(TMOD=Ox21;//SCON=0x50;TH0=(65536-50000)/256;TL0=(65536-50000)%256;THl=0xfd;TLl=0xfd;TR1=1;ET0=l;SM0=0;SM1=1;REN=1;EA=1;ES=1;)voiddisplay(ucharvalue)〃显示子函数(ucharbai,shi,ge;bai=value/100;〃分出百,十,和个位shi=value%100/10;ge=value%10;dula=l;PO=table[bai];〃送段选数据dula=0;P0=0xff;〃送位选数据前关闭所有显示,防止打开位选锁存时wela=l;〃原来段选数据通过位选锁存器造成混乱P0=0x7e;〃送位选数据
26wela=O;delayms(5);dula=l;PO=table[shi];dula=O;PO=Oxff;wela=l;P0=0x7d;wela=O;delayms(5);dula=l;PO=table[ge];dula=O;PO=Oxff;wela=l;P0=0x7b;wela=O;delayms(5);}ucharget_ad()(ucharadval;adwr=1;_nop_();adwr=O;-nop_();adwr=1;Pl=Oxff;adrd=1;_nop_();adrd=O;_nop_();advaI=Pl;adrd=l;returnadval;)voidmain()(init();wela=l;〃延时〃启动AD转换〃读取Pl口之前先给其写全1//AD读使能//AD数据读取〃置CSAD为〇,选通ADCS以后不必再管ADCSPO=Ox7f;wela=0;while(l)if(flag_uart==l)(flag_uart=0;ES=0;
27TI=1;switch(flag_on)(case0:puts(*Tumonad!
28*');TR0=l;break;case1:printf("Turnoffad!
29M);TR0=0;break;case2:puts("Error!
30");break;}while(!TI);〃必须要加TI=0;ES=1;)if(flag_time==l)(flag_time=0;ad_val=get_ad();ad_vo=(float)ad_val*5.0/256.0;ES=0;TI=1;printf('Thevoltageis%fV
31'\ad_vo);while(!TI);TI=0;ES=1;)display(ad_val);voidtimerOOinterrupt1(TH0=(65536-50000)/256;TL0=(65536-50000)%256;t0_num++;if(t0_num==20)(t0_num=0;flag_time=l;))voidser()interrupt4(RI=0;a=SBUF;flag_uart=l;
32if(a=l)flag_on=0;elseif(a==2)flag_on=l;elseflag_on=2;例721实现1602液晶的第一行显示“ILOVEMCU!”,在第二行显示WWW.TXMCU.COMo(part2.5_l.cP152)#include
33voidwrite_data(uchardate)(lcdrs=1;PO=date;delay⑸;lcden=l;delay(5);lcden=0;)voidinit()(dula=0;wela=0;lcden=0;write_com(0x38);〃设置!6X2显示,5X7点阵,8位数据接口write_com(0x0c);〃设置开显示,不显示光标write_com(0x06);〃写ー个字符后地址指针加1write_com(OxO1);〃显示清零,数据指针清零)voidmain()(init();write_com(0x80);for(num=O;num
34ucharcodetable1[]=HWelcometohere!sbitlcden=P3A4;〃液晶使能端sbitlcdrs=P3A5;〃液晶数据命令选择端sbitdula=P2A6i〃申明U1锁存器的锁存端sbitwela=P2A7;〃申明U2锁存器的锁存端ucharnum;voiddelay(uintz)(uintx,y;fbr(x=z;x>0;x—)fdr(y=I10;y>0;y—);)voidwrite_com(ucharcom){lcdrs=0;P0=com;delay⑸;lcden=l;delay(5);lcden=0;)voidwrite_data(uchardate)(lcdrs=1;PO=date;delay⑸;Icden=l;delay⑸;lcden=0;voidinit()(dula=0;wela=0;lcden=O;write_com(0x38);〃设置!6X2显示,5X7点阵,8位数据接口write_com(0x0c);〃设置开显示,不显示光标write_com(0x06);〃写ー个字符后地址指针加Iwrite_com(0x01);〃显示清零,数据指针清零)voidmain()(init();write_com(0x80+0x10);for(num=0;num<15;num-H-)|write_data(table[num]);
35delay⑸;}write_com(0x80+0x50);for(num=0;num<16;num++)(write_data(tablel[num]);delay(5);}for(num=0;num<16;num-H-){write_com(0xl8);delay(200);)while(l);)例7.3.1实现12232液晶的第一行显示“ILOVEMCU!”,第二行显示“我爱单片机”。(part2.5_3.cP160)#include 36SCLK=0;SCLK=1;i_data=i_data«l;)i_data=command_data;i_data&=0xf0;for(i=0;i<8;i++){SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data«l;)i_data=command_data;i_data«=4;for(i=0;i<8;i++)(SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data«l;)CS=0;delay_lms(10);voidsend_data(ucharcommand_data)(uchari;uchari_data;i_data=Oxfa;CS=1;for(i=0;i<8;i++)(SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data«1;}i_data=command_data;i_data&=0xf0;for(i=0;i<8;i++)(SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data«1; 37)i_data=command_data;i_data«=4;for(i=0;i<8;i++)(SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data«l;}cs=o;delay_lms(10);)voidlcd_init()(delay_lms(100);send_command(0x30);/*设置8位数据接口,基本指令模式。*/send_command(0x02);/*WDDRAM*/send_command(0x06);/*游标及显示右移一位・/send_command(OxOc);/*整体显示开,游标关,反白关・/send_command(0x01);/・写入空格清屏幕・/send_command(0x80);/・设定首次显示位置*/voiddisplay_s()(uchara;send_command(0x80);for(a=0;a 38for(i=0;i 39SCLK=O;SCLK=1;i_data=i_data«l;)i_data=command_data;i_data&=OxfO;for(i=0;iv8;i++)(SID=(bit)(i_data&0x80);SCLK=O;SCLK=1;i_data=i_data«1;)i_data=command_data;i_data«=4;for(i=0;i<8;i++)(SID=(bit)(i_data&0x80);SCLK=O;SCLK=I;i_data=i_data«1;)cs=o;delay_lms(1);)voidlcd_init()(delay」ms(100);send_command(0x30);/*设置8位数据接口,基本指令模式。*/send_command(0x02);/・清DDRAM*/send_command(0x06);/・游标及显示右移一位・/send_command(0x0c);/*整体显示开,游标关,反白关・/send_command(0x01);/*写入空格清屏幕・/send_command(0x80);/*设定首次显示位置*/voiddisplay_s(ucharnum)uchara;send_command(0x88-num);fbr(a=0;a<15;a++)(send_data(disps[a]);}}voiddisplay_x(ucharnum){uchara; 40send_command(0x98-num);fbr(a=0;a<15;a++){send_data(dispx(a]);}1main()(ucharaa;lcd_init();for(aa=0;aa<9;aa++)(display_s(aa);display_x(aa);delay_lms(300);}while(l);)例7.4.1实现在12864液晶上第一行显示“0123456789”,并且让每一位数字随机变化,第二行显示“www.txmcu.com”,第三行显示“天祥电子”,第四行对应第三行显示出下划线。(part2.5.5.cP173)#include 41sbitLCDRSsbitLCD_RW:sbitLCD_EN=sbitLCD_PSB=P3A5;P3ハ6;P3ハ4;P3ハ7;〃寄存器选择输入〃液晶读ノ写控制〃液晶使能控制〃串ノ并方式控制sbitwela=P2A6;sbitdula=P2A7;uchardisl[10];ucharcodedis2[]={"www.txmcu.com"};ucharcodedis3[]={"天祥电子”};ucharcodedis4[]={"");voiddelay_lms(uintx)(uintij;for(j=0;j 42P0=dat;delay」ms⑸;LCD.EN=1;delay_lms(5);LCD_EN=0;/・设定显示位置*/*/voidlcd__pos(ucharX,ucharY)(ucharpos;if(X==0){X=0x80;}elseif(X==l){X=0x90;}elseif(X==2){X=0x88;)elseif(X==3){X=0x98;)pos=X+Y;write_cmd(pos);〃显示地址}voidmakerand()(uintran;ran=rand();disl[0]=ran/10000+0x30;disl|l]=ran%10000/1000+0x30;disl[2]=ran%1000/100+0x30;disl[3]=ran%100/10+0x30;disl[4]=ran%10+0x30;ran=rand();disl[5]=ran/10000+0x30;disl[6]=ran%10000/1000+0x30;disl[7]=ran%1000/100+0x30;disl[8|=ran%100/10+0x30;disl[9]=ran%10+0x30; 43/*LCD初始化设定・//**/voidlcd_init()LCD_PSB=1;〃并口方式write_cmd(0x30);delay」ms⑸;〃基本指令操作write_cmd(0x0C);delay」ms⑸;〃显示开,关光标write_cmd(0x01);delay_lms(5);)〃清除LCD的显示内容氷・富*****************************************************/尸ツ/・主程序サ/*サmain()(uchari;wela=0;dula=0;delay_lms(10);〃延时lcd_init();〃初始化LCDlcd_pos(l,0);i=0;while(dis2[i]!=、0')(〃设置显示位置为第二行的第1个字符write_dat(dis2[i]);i++;)〃显示字符lcd_pos(2,0);i=0;while(dis3[i]!='〇')(〃设置显示位置为第三行的第1个字符write_dat(dis3[i]);i++;)〃显示字符lcd_pos(3,0);i=0;while(dis4[i]!=、〇')(〃设置显示位置为第四行的第1个字符write_dat(dis4[i]);〃显示字符i++;)while(l) 44{lcd_pos(0,0)J〃设置显示位置为第•行的第1个字符makerand();for(i=0;i<10;i++)(write_dat(disl[i]);)}知识点:生成随机数(part2.5_512232suiji.cP176)#include 45SCLK=O;SCLK=1;i_data=i_data«l;}i_data=command_data;i_data«=4;for(i=0;i<8;i++)(SID=(bit)(i_data&0x80);SCLK=O;SCLK=1;i_data=i_data«1;)cs=o;delay_lms(10);}voidsend_data(ucharcommand_data)(uchari;uchari_data;i_data=Oxfa;CS=1;for(i=0;i<8;i++)(SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data«l;)i_data=command_data;i_data&=0xf0;for(i=0;i<8;i++)(SID=(bit)(i_data&0x80);SCLK=0;SCLK=1;i_data=i_data«1;i_data=command_data;i_data«=4;for(i=0;i<8;i++)(SID=(bit)(i_data&0x80);SCLK=O;SCLK=1;i_data=i_data«l;} 46CS=O;delay_lms(10);)voidlcd_init()(delay_lms(100);send_command(0x30);/*设置8位数据接口,基本指令模式。*/send_command(0x02);/・清DDRAM*/send_command(0x06);/・游标及显示右移一位・/send_command(0x0c);/*整体显示开,游标关,反白关・/send_command(0x01);/*写入空格清屏幕・/send_command(0x80);/*设定首次显示位置・/)voiddisplay_s()(uchara;send_command(0x80);for(a=0;a<10;a++)(send_data(disps[a]);})voiddisplay_x()(uchara;send_command(0x92);for(a=0;a 47)main()(lcd_init();display_x();while(l){makerand();display_s();delay_lms(100);}while(l); 48例831利用定时器产生一个0〜99秒变化的秒表,并且显示在数码管上,每过一秒将这个变化的数写入板上AT24C02内部。当关闭实验板电源,并再次打开实验板电源时,单片机先从AT24C02中将原来写入的数读取出来,接着此数继续变化并显示在数码管上。(part2.6_l.cP188)#include 49scl=l;delay();sda=l;delay();)voidrespons()〃应答(uchari;scl=l;delay();while((sda==l)&&(i<250))i++;scl=O;delay();)voidinit()(sda=1;delay();scl=l;delay();}voidwrite_byte(uchardate)(uchari,temp;temp=date;for(i=0;i<8;i++){temp=temp«1;scl=O;delay();sda=CY;delay();scl=l;delay();}scl=O;delay();sda=1;delay();ucharread_byte()(uchari,k;scl=0;delay();sda=1;delay();for(i=0;i<8;i++)( 50scl=l;delay();k=(k«l)lsda;scl=O;delay();)returnk;)voidwrite_add(ucharaddress,uchardate)(start();write_byte(OxaO);respons();write_byte(address);respons();write_byte(date);respons();stop();}ucharread_add(ucharaddress)(uchardate;start();write_byte(OxaO);respons();write_byte(address);respons();start();write_byte(Oxal);response);date=read_byte();stop();returndate; 51voiddisplay(ucharbai_c,ucharsh_c)〃显示程序dula=0;PO=table[bai_c];dula=l;dula=0;wela=0;P0=0x7e;wela=l;wela=0;〃显示第一位delaylms(5);dula=0;PO=table[sh_c];dula=l;dula=0;wela=0;P0=0x7d;wela=l;wela=0;delaylms(5);}〃显示第二位voidmain()init();sec=read_add(2);if(sec>100)〃读出保存的数据赋アsec〃防止首次读取出错误数据sec=0;TMOD=0x01;ET0=l;EA=1;〃定时器工作在方式1TH0=(65536・50000)/256;〃对THOTLO赋值TL0=(65536-50000)%256;〃使定时器0.05秒中断一次TR0=l;while(l)〃开始计时display(sec/10,sec%10);if(write=l)〃判断计时器是否计时・秒{write=0;〃清零write_add(2,sec);〃在24co2的地址2中写入数据sec))voidt0()interruptI〃定时中断服务函数TH0=(65536-50000)/256;//对THOTLO赋值TL0=(65536-50000)%256;〃重装计数初值tcnt++;〃每过50mstent加一 52if(tcnt=20)//计满20次(1秒)时{tcnt=0;〃重新再计sec++;write=l;/"秒写一次24co2if(sec==100)〃定时100秒,再从零开始计时sec=0; 53例10.1.1利用定时器。工作方式0,在实验板上实现第一个发光管以1S亮灭闪烁。(part3.LLcP203)#include 54例10.2.1利用定时器0工作方式2,在实验板上实现第一个发光管以1s亮灭闪烁。(part3.12cP204)#include 55#defineucharunsignedchar#defineuintunsignedintsbitledl=PlAO;sbitled2=PlAl;uintnuml,num2;voidmain()(TMOD=0x03;〃设置定时器〇为工作方式3(00000011)TH0=6;〃装初值TL0=6;EA=1;〃开总中断ETO=1;〃开定时器〇中断ET1=1;〃开定时器1中断TRO=1;〃启动定时器〇TR1=1;〃启动定时器〇的髙8位计数器〃如果到了3686次,说明1秒时间到〃然后把numl清〇重新再计3686次〃让发光管状态取反〃如果到了1843次,说明半秒时间到〃然后把num2清〇而:新再计1843次〃让发光管状态取反while(l)〃程序停止在这里等待中断发生if(numl>=3686)(numl=0;led1二〜led1;)if(num2>=1843)(num2=0;Ied2=-led2;)))voidTL0_time()interrupt1(TL0=6i〃重装初值num1++;}voidTH0_time()interrupt3(TH0=6;〃重装初值num2++; 56例10.5.1利用计数器0工作方式1,在实验板上实现:用ー根导线一端连接GND引脚,另一端去接触T0(P3.4)引脚,每接触一下,计数器计ー次数,将所计的数值实时显示在数码管的前两位,计满!00时清0,再从头计起。(parts.1.4.CP214)#include 57forC=110;j>0;j-);}uintread()uchartl,thl,th2;uintval;while(l)(thl=THO;tl=TLO;th2=TH0;if(thl==th2)break;)val=thl*256+tl;returnval;)voidmain()(uchara,b;uintnum;TMOD=0x05;〃设置计数器〇为工作方式1(00000101)TH0=0;〃将计数器寄存器初值清零TL0=0;TRO=1;while(l){num=read();if(num>=100)(num=0;TH0=0;〃将计数器寄存器值清零TL0=0;}a=num/10;b=num%10;display(a,b); 58例11.1.1设置单片机串行口的工作模式〇,间隔循环发送十六进制数OxAA,然后用双路示波器观察P3.0和P3.1口波形。(part3.2.1.cP218)#include 59EA=1;ES=1;TI=0;while(l){SBUF=0xaa;delayms(l);))voidserO()interrupt4(TI=O;}例11.2.1设置单片机串行口工作模式2,间隔循环发送16进制数OxAA,然后用示波器观察单片机P3.1口波形。(part322.cP220)#include 60线连接连个单片机的P3.0和P3.1ロ(共地)。在ー块板上编写矩阵键盘扫描程序,当扫描到有键按下时,将键值通过串口发送出去,另ー块板上单片机收到串口发送来的键值后,将对应键值以0~F方式显示在数码管上。发送方单片机程序代码(part3.2.3.cP225)#include 61break;caseOxbe:key=2;break;case0x7e:key=3;break;}while(temp!=OxfO)(temp=P3;temp=temp&OxfO;}send(key);))P3=Oxfd;temp=P3;temp=temp&OxfO;if(temp!=OxfO)(delayms(lO);temp=P3;temp=temp&OxfO;if(temp!=OxfO){temp=P3;switch(temp)(caseOxed:key=4;break;caseOxdd:key=5;break;caseOxbd:key=6;break;caseOx7d:key=7;break;}while(temp!=OxfO) 62{temp=P3;temp=temp&OxfO;}send(key);)}P3=Oxfb;temp=P3;temp=temp&OxfO;if(temp!=OxfO)(delayms(lO);temp=P3;temp=temp&OxfO;if(temp!=OxfO){temp=P3;switch(temp)(caseOxeb:key=8;break;caseOxdb:key=9;break;caseOxbb:key=10;break;caseOx7b:key=l1;break;)while(temp!=OxfO)temp=P3;temp=temp&OxfO;)send(key);}}P3=Oxf7;temp=P3;temp=temp&OxfO;if(temp!=OxfO)(delayms(lO);temp=P3; 63temp=temp&OxfO;if(temp!=OxfO)(temp=P3;switch(temp)(case0xe7:key=12;break;case0xd7:key=13;break;case0xb7:key=14;break;case0x77:key=15;break;)while(temp!=OxfO)(temp=P3;temp=temp&OxfO;)send(key);)))voidmain()TMOD=0x20;THl=Oxfd;TLl=Oxftl;TR1=1;SMO=O;SM1=1;EA=1;ES=1;while(l){matrixkeyscan。;〃不停调用键盘扫描程序)}接收方单片机程序代码part3.24c如下:#include 64#defineucharunsignedchar#defineuintunsignedintsbitdula=P2A6;〃申明UI锁存器的锁存端sbitwela=P2A7;〃申明U2锁存器的锁存端ucharcodetable[|={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71);voiddisplay(ucharnum)(P0=table|num];〃显示函数只送段选数据dula=l;dula=0;}voidmain()(TMOD=0x20;THl=0xfd;TLl=0xfd;TR1=1;REN=1;SM0=0;SM1=1;EA=1;ES=1;P0=0xc0;〃位选中所有数码管wela=l;wela=0;while(l),等待串口中断产生,然后更新显示voidser()interrupt4(uchara;RI=O;a=SBUF;display(a);)例11.4.1程序分为主机程序和从机程序,约定一次传送的数据为16B,以02H地址的从机为例。(图11.4.2为多机通信主机程序流程图)主机程序代码:(part3.2.5.cP232)#include 65#defineBN16ucharrbuf[16];ucharcodetbuf[16]={"mastertransmit"};voiderr(void)(SBUF=0xff;while(Tl!=1);TI=0;)ucharmaster(ucharaddr,ucharcommand)(ucharaa,i,p;while(l){SBUF=SLAVE;/・发呼叫地址・/while(TI!=l);TI=0;while(RI!=l);RI=0;/*等待从机回答・/if(SBUF!=addr)err();/・若地址错,发复位信号・/else{/・地址相符*/TB8=0;/・清地址标志・/SBUF=command;/・发命令・/while(TI!=1);TI=O;while(RI!=l);RI=O;aa=SBUF;/・接收状态・/if((aa&OxO8)==OxO8)/・若命令未被接收,发复位信号・/(TB8=1;err();}else(if(command==OxO1)/・是发送命令・/(if((aa&0x01)==0x01)/・从机准备好接收*/(do{P=0;/・清校验和*/for(i=0;i 66return(O);)else{if((aa&OxO2)==OxO2)/・是接收命令,从机准备好发送・/(while(l)p=0;/・清校验和*/ 67for(i=0;i 68图11.4.3为多机通信从机程序流程图。从机程序代码:(part3.2.6.cP234)#include 69}else(if(a=0x02)/・从机向主机发送数据・/(if(tready==l)SBUF=0x02;/・发送准备好发状态・/elseSBUF=0x00;while(TI!=l);TI=0;while(RI!=l);RI=0;if(RB8==l)SM2=1;ES=1;gotoreti;)str();/・发送数据・/}else(SBUF=0x80;/・命令非法,发状态・/while(TI!=l);TI=0;SM2=1;ES=1;/*恢复监听・/reti:;)voidstr(void)/・发数据块・/(ucharp,i;tready=0;do(p=0;/・清校验和*/for(i=0;i 70RI=0;}while(SBUF!=0);/・主机接收不正确,重新发送・/SM2=1;ES=1;)voidsre(void)/・接收数据块・/(ucharp,i;rready=0;while(l) 71p=0;/・清校验和*/for(i=0;i 72(for(a=0;a<30000;a++);〃延时・段时间Pl=*finger;〃从指针指向的地址取数据到P1ロfinger++;〃指针加一,))while(l);例13.1.1编写程序实现:开启两个外部中断,设置低电平触发中断,用定时器计数并且显示在数码管的前两位,当计数到5时,使单片机进入空闲(休眠)模式,同时关闭定时器,当单片机响应外部中断后,从空闲(休眠)模式返回,同时开启定时器。(part3.4.1.cP266)#include 73P0=0xfd;wela=0;delayms(5);)voiddelayms(uintxms)(uinti,j;for(i=xms;i>0;i—)//i=xms即延时约xms毫秒for(j=110;j>0;j-);}voidmain()(uchara,b,numl;TMOD=0x01;〃设置定时器〇为工作方式!(00000001)TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ET0=l;EX0=l;EX1=1;TR0=l;while(l){if(num>=20)num=O;num1++;if(numl==6)(ETO=O;PCON=0x03;)a=num1/10;b=numl%10;)display(a,b);))voidtimer0()interrupt1(TH0=(65536-50000)/256;TL0=(65536-50000)%256;num++;)voidex_intO()interrupt0(PCON=0;ET0=l;}voidex_intl()interrupt2(PCON=0;ET0=l;}例13.2.1实验板上实现如下描述:程序启动后设定看门狗溢出时间为2s,然后点亮第一个发光二极管,稍延时一会,然后熄灭发光二极管,使程序进入等待死循环状态,并且在死循环中大约每隔!S喂狗一次,看程序运行是否正常。(pa.42cP270) 74#include 75wela=0;delayms⑸;〃延时dula=l;PO=table[ge];〃送个位段选数据dula=O;PO=Oxff;wela=l;PO=Oxfd;wela=O;delayms(5);)voiddelayms(uintxms)(uinti,j;for(i=xms;i>0;i—)//i=xms即延时约xms毫秒for(j=110;j>0;j-);1voidmain()(uchara,b,numl;TMOD=0x01;〃设置定时器〇为工作方式1(00000001)TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ETO=1;TR0=l;while(l)(if(num>=20){num=0;numl++;if(numl==10)(ISP_CONTR=0x20;}a=numl/10;b=numl%10;)display(a,b);})voidtimerO()interrupt1(TH0=(65536-50000)/256;TL0=(65536-50000)%256; 76num++;例13.61在实验板上实现:操作STC单片机自带的E2PR0M,存储ー组按秒递增的两位数据,并且将数据实时显示在数码管上,数据每变化一次就往E2PR0M中写入一次,当关闭实验板电源并再次开启电源时,从E2PR0M中读取先前存储的数据,接着递增显示。(part3.4.3.cP279)#include 77duia=l;PO=table[shi];〃送十位段选数据dula=0;PO=Oxff;〃送位选数据前关闭所有显示,防止打开位选锁存时wela=l;〃原来段选数据通过位选锁存器造成混乱P0=0xfe;〃送位选数据wela=0;delayms(5);〃延时dula=l;PO=table[ge];〃送个位段选数据dula=0;PO=Oxff;wela=l;P0=0xfd;wela=0;delayms(5);/*=============打开!SP,IAP功能===========*/voidISP_IAP_enable(void)(EA=0;/*关中断*/ISP.CONTR=ISP.CONTR&0xl8;/*0001.1000*/ISP.CONTR=ISP.CONTRIWaitTime;/・写入硬件延时・/1SP_CONTR=ISP_CONTR10x80;/*1SPEN=1*/)/*==========关闭ISP,IAP功能============*/voidISP_IAP_disable(void)(ISP_CONTR=ISP_CONTR&0x7f;/*ISPEN=0*/ISP_TRIG=0x00;EA=1;/・开中断*/)/*================公用的触发代码====================*/voidISPgoon(void)ISP_IAP_enable();/・打开!SP.IAP功能・/ISP_TRIG=0x46;/・触发ISP_IAP命令字节1*/ISP.TRIG=0xb9;/・触发ISP」AP命令字节2*/_nop__();/*=========字节读===========*/unsignedcharbyte_read(unsignedintbyte_addr)ISP_ADDRH=(unsignedchar)(byte_addr»8);/・地址赋值・/ISP_ADDRL=(unsignedchar)(byte_addr&OxOOff);ISP_CMD=ISP.CMD&Oxf8;/・清除低3位ウISP_CMD=ISP_CMD1RdCommand;/・写入读命令ウISPgoon();/・触发执行・/ISP_IAP_disable();/*关闭ISPIAP功能・/return(ISP_DATA);/・返回读到的数据・/)/*============扇区擦除=================*/voidSectorErase(unsignedintsector_addr) 78unsignedintiSectorAddr;iSectorAddr=(sector_addr&OxfeOO);/・取扇区地址・/ISP_ADDRH=(unsignedchar)(iSectorAddr»8);1SP_ADDRL=0x00;ISP.CMD=ISP_CMD&Oxf8;/・清空低3位・/ISP.CMD=ISP.CMDIEraseCommand;/・擦除命令3*/ISPgoon();/・触发执行・/ISP」AP_disable();/*关闭ISPJAP功能・/)/*==============字节写==================*/voidbyte_write(unsignedintbyte_addr,unsignedcharoriginal_data)(ISP_ADDRH=(unsignedchar)(byte_addr»8);/・取地址・/ISP_ADDRL=(unsignedchar)(byte_addr&OxOOff);ISP_CMD=ISP.CMD&Oxf8;/・清低3位・/ISP_CMD=ISP_CMDIPrgCommand;/*写命令2*/ISP_DATA=original_data;/・写入数据准备ISPgoon();/・触发执行ISP_IAP_disable();/*关闭IAP功能*/*/)voidmain()(uchara,b,numl;TMOD=0x01;〃设置定时器0为工作方式1(00000001)TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ET0=l;TR0=l;numl=byte_read(0x2000);〃程序开始时读取EEPROM中数据if(numl>=60)〃防止首次上电时读取出错num1=0;while(l)if(num>=20)(num=0;numl++;SectorErase(0x2000);〃擦除扇区byte_write(0x2000,num1);〃重新写入数据if(numl==60)(num1=0;}a=numl/10;b=numl%10;}display(a,b); 79)}voidtimer0()interrupt1(TH0=(65536-50000)/256;TL0=(65536-50000)%256;num++;}例13.7.1STC89LE516AD/X2系列单片机的A/D转换功能。时钟11.0592MHz,转换结果以16进制形式输出到串行口,可以用串行口调试程序,观察输出结果(本代码摘自宏晶科技芯片手册,经作者调试可正常运行)。(part3.45cP283)#include 80AD_finished=0;while(AD_finished==0)/Z等待A/D转换结束{AD_finished=(ADC_CONTR&0x10);//0001,0000,ADC_FLAG==1测试A/D转换结束否ADC_CONTR&=0xF7;//1111,0111令ADC_START=0.关闭A/D转换,return(ADC_DATA);//返回A/D转换结果)voidmain()(initiate_RS232();Pl=PlI0x63;〃0110,0011,要设置为A/D转换的Pl.x□,先设为高P1_ADC_EN=0x63;//0110,0011,P!的P1.O,P1.1,P1.5,P1.6设置为A/D转换输入脚/Z断开P1.O,P1.1,P1.5,P1.6内部上拉电阻while(l)Send_Byte(get_AD_result(O));//P1.0为A/D当前通道,测量并发送结果delay(0x200);Send_Byte(get_AD_result(1));//P1.1为A/D当前通道,测量并发送结果delay(0x200);Send_Byte(get_AD_result(5));//Pl.5为A/D当前通道,测量并发送结果delay(0x200);Send_Byte(get_AD_result(6));//P1.6为A/D当前通道,测量并发送结果delay(0x200);Send_Byte(O);/Z连续发送4个00H,便于观察输出显示Send_Byte(O);Send_Byte(O);Send_Byte(O);delay(0x200);/Z延时delay(0x200);delay(0x200);delay(0x200);delay(0x200);delay(0x200);})例1381给出ー个STC12C5412AD应用的参考程序。(part3.4.6.cP287)#include,(STC12C5410AD.H,I〃STC12c54系列单片机头文件#defineucharunsignedchar#defineuintunsignedintvoiddelayms(uintxms)( 81uinti,j;for(i=xms;i>0;i—)//i=xms即延时约xms毫秒for(j=110;j>0;j-);)voidAD」nit()(PlM0=0x0f;//00001111设置Pl口低4位为开漏模式,用来AD采集PlMl=0x0f;//00001111ADC_CONTR=OxeO;//l1100000开启AD转换器电源,设置最高转换速度delayms(lOO);)intGetAD(unsignedcharchannel)//channe!为要取的通道号(〇〜7)unsignedcharAD_finished=O;intresult;ADC_CONTRl=channel;〃选择AD通道号ADC_CONTRI=0x08;〃启动AD转换while(AD一flnished=O)〃等待AD转换结束{AD_finished=(ADC_CONTR&Oxl〇);〃查询ADC一FLAG位是否置1}代sult=ADC一DATA*4+ADC一LOW2;〃读走AD转换结果,由于ADC_DATA中存储12位中的〃髙8位,当要转换成10进制时,需将ADC-DATA中的数左移2位,即相当于・4ADC_CONTR&=Oxf7;〃清除转换结束标志return(result);〃返回结果给函数)floatAd_Av(ucharchannel)〃求100次采集电压的平均值{floatVal_Av=0;ucharnum;for(num=100;num>0;num—){Val_Av+=GetAD(channel)y/100次采集求和}Val_Av/=100.0;〃求平均值Val_Av=Val_Av*5.0/1024;〃单片机电源为5V,求的真实电压值return(Val_Av);〃返回给函数)voidmain()(floatadl,ad2,ad3,ad4;ADJnitO;adl=Ad_Av(l);ad2=Ad_Av(2);ad3=Ad_Av(3);ad4=Ad_Av(4);while(l);)以下为STC12c5410AD.H中除去原51单片机寄存器地址定义部分的内容: 82/*AfterisSTCadditionalSFRorchange*//*sfrAUXR=0x8e;*//*sfrIPH=0xb7;*//*WatchdogTimerRegister*/sfrWDT_CONTR=0xel;/*ISP_IAP_EEPROMRegister*/sfrISP_DATA=0xe2;sfrISP.ADDRH=0xe3;sfrISP_ADDRL=0xe4;sfrISP_CMD=0xe5;sfrISP_TRIG=0xe6;sfrISP_CONTR=Oxe7;/*SystemClockDivider*/sfrCLK_DIV=0xc7;/*I_OPortModeSetRegister*/sfrPOMO=0x93;sfrPOM1=0x94;sfrPIMO=0x91;sfrPIMl=0x92;sfrP2M0=0x95;sfrP2M1=0x96;sfrP3M0=Oxbl;sfrP3Ml=Oxb2;/*SPIRegister*/sfrSPSTAT=0x84;sfrSPCTL=0x85;sfrSPDAT=0x86;/*ADCRegister*/sfrADC_CONTR=0xc5;sfrADC_DATA=0xc6;sfrADC_LOW2=Oxbe;/*PCASFR*/sfrCCON=0xD8;sfrCMOD=0xD9;sfrCCAPM0=OxDA;sfrCCAPMl=0xDB;sfrCCAPM2=0xDC;sfrCCAPM3=OxDD;sfrCCAPM4=0xDE;sfrCCAPM5=0xDF;sfrCL=0xE9;sfrCCAPOL=OxEA;sfrCCAPiL=OxEB;sfrCCAP2L=0xEC;sfrCCAP3L=0xED;sfrCCAP4L=0xEE;sfrCCAP5L=0xEF;sfrCH=0xF9;sfrCCAPOH=OxFA;sfrCCAP!H=OxFB;sfrCCAP2H=OxFC;sfrCCAP3H=OxFD;sfrCCAP4H=OxFE;sfrCCAP5H=OxFF; 83sfrPCA_PWMO=OxF2;sfrPCA_PWM1=OxF3;sfrPCA_PWM2=0xF4;sfrPCA_PWM3=OxF5;sfrPCA_PWM4=0xF6;sfrPCA_PWM5=OxF7;/*CCON*/sbitCF=CCONA7;sbitCR=CCONA6;sbitCCF5=CCONA5;sbitCCF4=CCONA4;sbitCCF3=CCONA3;sbitCCF2=CCONA2;sbitCCF1=CCONA1;sbitCCFO=CCONA0;/*AboveisSTCadditionalSFRorchange*/REG51F.HHeaderfilefor8xC31/51,8OC51Fx,80C51Rx+Copyright(c)1988-1999KeilElektronikGmbHandKeilSoftware,Inc.Allrightsreserved.ModificationaccordingtoDatasheetfromApril1999-SFR'sAUXRandAUXRIaddedfor80C51Rx+derivatives*//*BYTERegisters*/sfrPO=0x80;sfrPl=0x90;sfrP2=OxAO;sfrP3=OxBO;sfrPSW=OxDO;sfrACC=OxEO;sfrB=OxFO;sfrSP=0x81;sfrDPL=0x82;sfrDPH=0x83;sfrPCON=0x87;sfrTCON=0x88;sfrTMOD=0x89;sfrTLO=0x8A;sfrTL1=0x8B;sfrTHO=0x8C;sfrTH1=0x8D;sfrIE=0xA8;sfrIP=0xB8;sfrSCON=0x98;sfrSBUF=0x99;/*80C51Fx/RxExtensions*/sfrAUXR=0x8E;/*sfrAUXRI=0xA2;*/sfrSADDR=OxA9; 84sfrIPH=0xB7;sfrSADEN=0xB9;sfrT2C0N=0xC8;sfrT2MOD=0xC9;sfrRCAP2L=0xCA;sfrRCAP2H=0xCB;sfrTL2=0xCC;sfrTH2=OxCD;/*BITRegisters*//*PSW*/sbitCY=PSWA7;sbitAC=PSWA6;sbitFO=PSWA5; 85sbitRS1=PSWA4;sbitRSO=PSWA3;sbitOV=PSW八2;sbitP=PSWA〇;/*TCON*/sbitTF1=TCONA7;sbitTR1=TCONA6;sbitTFO=TCONA5;sbitTRO=TCONA4;sbitIE1=TCONA3;sbitIT1=TCONA2;sbitIEO=TCONA1;sbitITO=TCONA0;/*P3*/sbitRD=P3A7;sbitWR=P3A6;sbitTl=P3A5;sbitTO=P3A4;sbitINTI=P3A3;sbitINTO=P3A2;sbitTXD=P3A1;sbitRXD=P3AO;SCON*/sbitSMOsbitFEsbitSMIsbitSM2sbitRENsbitTB8sbitRB8sbitTIsbitRI=SCONA7;//alternatively"FE"=SCONA7;=SCONA6;=SCONA5;=SCONA4;=SCONA3;=SCONA2;=SCONA1;=SCONA0;sbitT2EX=P1A1;sbitT2=P1AO;/*T2CON*/sbitTF2=T2CONA7;sbitEXF2=T2CONA6;sbitRCLK=T2CONA5;sbitTCLK=T2CONA4; 86sbitEXEN2=T2CONA3;sbitTR2=T2CONA2;sbitC_T2=T2CONA1;sbitCP_RL2=T2CONA0;/*PCAPin*/sbitCEX3=P2A4;sbitCEX2=P2A0;sbitCEX1=P3A5;sbitCEXO=P3A7;sbitECI=P3A4;/*IE*/sbitEA=IEA7;sbitEPCA_LVD=IEA6;sbitEADC_SPI=IEA5;sbitES=IEA4;sbitET1=IEA3;sbitEXI=IEA2;sbitETO=IEA1;sbitEXO=IEAO;/*IP*/sbitPPCA_LVD=IPA6;sbitPADC_SPI=IPA5;sbitPS=IPA4;sbitPT1=IPA3;sbitPX1=IPA2;sbitPTO=IPA1;sbitPXO=IPAO;STC_ADC.HsfrPl_ADC_EN=0x97;sfrADC_CONTR=Oxc5;sfrADC_DATA=0xc6;intGetAD(unsignedcharchannel)〃用户函数,channel为要取的通道号(〇〜7)unsignedcharAD_finished=O;//AD_lnit(l«channel);ADC_DATA=O;ADC_CONTR=channel;delay(lOOO); 87ADC_CONTRI=0x08;AD_finished=O;while(AD_finished=O){AD_finished=(ADC_CONTR&Ox10);}ADC_CONTR&=OxF7;return(ADC_DATA);voidAD_Init(unsignedcharADin)//ADC初始化,ADin为ハ位2进制数,分别对应AD7〜0,置1代表打开此路(Pl=PllADin;Pl_ADC_EN=0x63;程序14.3.1利用51单片机的定时器设计ー个时钟。〃晶振:TX-1C实验板上实际晶振为11.0592M,〃这里为了方便计算时间,我们假设晶振为12M.#include 88sbitbeep=P2A3;〃定义蜂鸣器端ucharcount,s1num;charmiao,shi,fen;ucharcodetable[]="2008-9-30MON”;〃定义初始上电时液晶默认显示状态voiddelay(uintz)〃延时函数(uintx,y;for(x=z;x>0;x—)for(y=110;y>0;y-);)voiddi()〃蜂鸣器发声函数(beep=0;delay(lOO);beep=1;Ivoidwrite_com(ucharcom)〃液晶写命令函数(rs=O;lcden=0;P0=com;delay⑸;lcden=l;delay(5);lcden=0;)voidwrite_date(uchardate)〃液晶写数据函数(rs=l;lcden=0;PO=date;delay⑸;lcden=l;delay⑸;lcden=0;)voidwrite_sfm(ucharadd,uchardate)〃写时分秒函数ucharshi,ge;shi二date八〇;〃分解ー个2位数的十位和个位ge=date%10;write_com(0x80+0x40+add);〃设置显示位置write_date(0x30+shi);〃送去液晶显示十位write_date(0x30+ge);〃送去液晶显示个位 89}voidinit()〃初始化函数(ucharnum;rd=O;〃软件将矩阵按键第4列一端置低用以分解出独立按键dula=O〃关闭两锁存器锁存端,防止操作液晶时数码管会出乱码wela=0;lcden=O;fen=O;〃初始化种变量值miao=0;shi=O;count=0;slnum=0;init_24c02();write_com(0x38);〃初始化1602液晶write_com(0x0c);write__com(0x06);write_com(OxO1);write_com(0x80)ン/设置显示初始坐标for(num=0;numvl5;num++)〃显示年月日星期{write_date(table[num]);delay(5);)write_com(0x80+0x40+6);〃写出时间显示部分的两个冒号write_date(y);delay⑸;write_com(0x80+0x40+9);write_date(,:*);delay(5);miao=read_add⑴;〃首次上电从AT24C02中读取出存储的数据fien=read_add(2);shi=read_add(3);write_sfm(10,miao)ンノ分别送去液晶显示write_sfm(7,fen);write_sfm(4,shi);TMOD=0x01;〃设置定时器〇工作模式1TH0=(6553&50000)/256;〃定时器装初值TL0=(65536-50000)%256;EA=1;〃开总中断ETO=1;〃开定时器〇中断TRO=1;〃启动定时器。)voidkeyscan。〃按键扫描函数(if(sl=O) 90{delay(5);if(sl=O)〃确认功能键被按下{slnum++;〃功能键按下次数记录while(isl);〃释放确认di。;〃每当有按键释放蜂鸣器发出滴声if(s1num==1)〃第一次被按下时(TR0=0;〃关闭定时器write_com(0x80+0x40+10);//光标定位到秒位置write.com(OxOf);//光标开始闪烁}if(slnum==2)〃第二次按下光标闪烁定位到分钟位置{write_com(0x80+0x40+7);)if(slnum==3)//第三次按下光标闪烁定位到小时位置(write_com(0x80+0x40+4);)if(s1num==4)〃第四次按下(slnum=0;〃记录按键数清零write_com(0x0c);〃取消光标闪烁TRO=1;〃启动定时器使时钟开始走)))if(slnum!=0)〃只有功能键被按下后,增加和减小键オ有效(if(s2=0){delay(5);if(s2==0)〃增加键确认被按下while(!s2);〃按键释放di();〃每当有按键释放蜂鸣器发出滴声if(slnum=l)〃若功能键第一次按下{miao++;//则调整秒加1if(miao==60)〃若满60后将清零miao=0;write_sfm(10,miao);〃每调节一次送液晶显示一下 91write_com(0x80+0x40+10);〃显示位置重新回到调节处write_add(l,miao);〃数据改变立即存入24CO2)if(slnum=2)〃若功能键第二次按下{生n++;〃则调整分钟加1if(fen==60)〃若满60后将清零fen=0;write_sfm(7,fen);〃每调节一次送液晶显示一下write_com(0x80+0x40+7);〃显示位置重新回到调节处write_add(2,fen);〃数据改变立即存入24C02}if(s1num==3)〃若功能键第三次按下(shi++;〃则调整小时加1if(shi=24)"若满24后将清零shi=0;write一sfm(4,shi);;〃每调节一次送液晶显示一下write一coin(0x80+0x40+4);〃显示位置重新回到调节处write.add(3,shi);〃数据改变立即存入24co2if(s3==0){delay(5);if(s3=0)〃确认减小犍被按下{while(!s3);〃按键释放di();〃每当有按键释放蜂鸣器发出滴声if(slnum==l)〃若功能键第一次按下{miao--;〃则调整秒减1if(miao==-l)//若减到负数则将其重新设置为59miao=59;write_sfm(10,miao);〃每调节一次送液晶显示・下write_com(0x80+0x40+10);〃显示位置重新回至リ调节处write-add(Ltniao)メ数据改变立即存入24C02)if(slnum=2)〃若功能键第二次按下{fen-r〃则调整分钟减1 92if(fen==-l)〃若减到负数则将其重新设置为59fen=59;write_sfm(7,fen);〃每调节一次送液晶显示一下write_com(0x80+0x40+7);〃显示位置重新回到调节处write_add(2,fen);〃数据改变立即存入24C02)if(slnum=3)〃若功能键第二次按下(shi-;//则调整小时减!if(shi=-1)〃若减到负数则将其重新设置为23shi=23;write一sftn(4,shi);//每调节ー一次送液晶显示一下write一com(0x80+0x40+4);〃显示位置重新回到调节处write_add(3,shi);〃数据改变立即存入24C02)))voidmain。〃主函数(init();〃首先初始化各数据while(1)〃进入主程序大循环{keyscan。;〃不停的检测按健是否被按下})voidtimer0()interrupt1〃定时器〇中断服务程序|TH0=(65536-50000)/256;〃再次装定时器初值TL0=(65536-50000)%256;count++!〃中断次数累加if(count==20)//20次50毫秒为1秒(count=0;miao++;if(miao==60)//秒加至リ60则进位分钟miao=0;〃同时秒数清零fen++;if(fen==60)〃分钟加至U60则进位小时(fen=0;〃同时分钟数清零 93shi++;if(shi=24)〃小时加到24则小时清零{shi=0;)write_sfm(4,shi);〃小时若变化则重新写入write一add(3,shi);〃数据改变立即存入24co2}\¥由€_$1'111(7A11);〃分钟若变化则重新写入write-add(2,fen);〃数据改变立即存入24C02)write_sfm(10,miao);〃秒若变化则重新写入write一add(l,miao);〃数据改变立即存入24C0224co2.h是TX-1C板上E2PROM操作函数,其源代码如下:(P319)bitwrite=0;〃写24C02的标志:sbitsda=P2A0;sbitscl=P2A1;voiddelay0()(;;)voidstart()〃开始信号(sda=1;delayO();scl=l;delayO();sda=O;delayO();}voidstop()〃停止{sda=0;delayOO;scl=l;delayO();sda=1;delayO();voidrespons()〃应答(uchari;scl=l;delayO();while((sda==1)&&(i<250))i++;scl=0; 94delayO();)voidinit_24cO2()//IIC初始化函数(sda=1;delayO();scl=l;delayO();}voidwrite_byte(uchardate)〃写ー个字节函数(uchari,temp;temp=date;for(i=0;i<8;i++){temp=temp«l;scl=O;delayOO;sda=CY;delayO();scl=l;delayOO;}scl=O;delayO();sda=1;delay0();}ucharread_byte()〃读ー个字节函数(uchari,k;scl=O;delayOO;sda=1;delayO();for(i=0;i<8;i++)scl=l;delayO();k=(k«l)lsda;scl=O;delayOO;)returnk;)voidwrite_add(ucharaddress,uchardate)〃指定地址写ー个字节(start();write_byte(OxaO);respons();write_byte(address); 95respons();write_byte(date);respons();stop();)charread_add(ucharaddress)〃指定地址读ー个字节(uchardate;start();write_byte(OxaO);respons();write_byte(address);respons();start();write_byte(Oxal);respons();date=read_byte();stop();returndate;)程序15.5.1使用DS12C887时钟芯片设计高精度时钟。(part4.2P331)#include 96}voidwrite_date(uchardate){〃写液晶数据函数rs=l;lcden=0;PO=date;delay⑶;lcden=l;delay(3);lcden=0;)voidinit(){〃初始化函数ucharnum;EA=1"打开总中断EX1=1;〃开外部中断IIT1=1;〃设置负跳变沿触发中断flagl=O;〃变量初始化tO_num=O;slnum=0;week=l;dula=0ル关闭数码管显示wela=0;lcden=0;rd=O;/・以下儿行在首次设置DS12c887时使用,以后不必再写入write_ds(0x0A,0x20);〃打开振荡器write_ds(0x0B,0x26);〃设置24小时模式,数据二进制格式〃开启闹铃中断setjime。;//设置上电默认时间*/write_com(0x38);//1602液晶初始化write_com(OxOc);write_com(0x06);write_com(OxO1);write_com(0x80);for(num=0;num 97delay(l);)}voidwrite_sfm(ucharadd,chardate){〃1602液晶刷新时分秒函数4为时,7为分,10为秒charshi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_date(0x30+shi);write_date(0x30+ge);}voidwrite_nyr(ucharadd,chardate){〃1602液晶刷新年月日函数3为年,6为分,9为秒charshi,ge;shi=date/10;ge=date%10;write_com(0x80+add);write__date(0x30+shi);write_date(0x30+ge);)voidwrite_week(charwe){〃写液晶星期显示函数write_com(0x80+12);switch(we)case1:write_date(,M');delay(5);write_date(,O,);delay(5);write_dale(N);break;case2:write_date(T');delay(5);write_date(U);delay(5);write_date(E);break;case3:write_date(*W*);delay(5);write_date(E);delay(5);write_date(D');break;case4:write_date(T');delay(5);write_date('H');delay(5);write_date(,U,);break;case5:write_date(F);delay⑸;write_date(R');delay(5);write_date(T);break;case6:write_date('S*);de1ay(5);write_date(1A1);delay(5);write_date(T');break; 98case1:write_date(,S,);delay(5);write_date(,U');delay(5);write_date(N);break;voidkeyscan()if(flag_ri==l){〃这里用来取消闹钟报警,任ー键取消报警if((sl=0)||(s2==0)ll(s3=0)ll(s4==0))(delay(5);if((sl=0)||(s2==0)ll(s3=0)ll(s4==0))while(!(s1&&s2&&s3&&s4));di();flag_ri=O;〃清除报警标志)if(sl=o)〃检测S1(delay(5);if(sl=0)(s1num++;〃记录按下次数if(flagl==l)if(slnum=4)slnum=l;flag=l;while(!sl);di();switch(slnum){〃光标闪烁点定位case1:write_com(0x80+0x40+10);write_com(0x0f);break;case2:write_com(0x80+0x40+7);break;case3:write_com(0x80+0x404-4);break;case4:write_com(0x80+12);break;case5:write_com(0x80+9);break;case6:write_com(0x80+6);break;case7:write_com(0x80+3);break; 99case1:slnum=0;write_com(0x0c);flag=0;write_ds(0,miao);write_ds(2,fen);write_ds(4,shi);write_ds(6,week);write_ds(7,day);write_ds(8,month);write_ds(9,year);break;)})if(slnum!=0)〃只有当SI按下后,オ检测S2和S3if(s2==0){delay(l);if(s2==0){while(!s2);di();switch(slnum){〃根据功能键次数调节相应数值case1:miao++;if(miao==60)miao=0;write_sfm(10,miao);write_com(0x80+0x40+10);break;case2:fen++;if(fen==60)fen=0;write_sfm(7,fen);write_com(0x80+0x404-7);break;case3:shi++;if(shi=24)shi=0;write_sfm(4,shi);write_com(0x80+0x40+4);break;case4:week-H-;if(week==8)week=l;write_week(week); 100write_com(0x80+12);break;case1:day++;if(day==32)day=l;write__nyr(9,day);write_com(0x80+9);break;case2:month++;if(month==13)month=l;write_nyr(6,month);write_com(0x804-6);break;case3:year++;if(year==100)year=0;write_nyr(3,year);write_com(0x80+3);break;)))if(s3=0){delay(l);if(s3==0)(while(!s3);di();switch(slnum){〃根据功能键次数调节相应数值case1:miao—;if(miao==-l)miao=59;write_sfm(10,miao);write_com(0x80+0x40+10);break;case2:fen—;if(fen==-l)fen=59;write_sfm(7,fen);write_com(0x80+0x40+7);break;case3:shi—; 101if(shi==-l)shi=23;write_sfm(4,shi);write_com(0x80+0x40+4);break;case1:week—;if(week==O)week=7;write_week(week);write_com(Ox8(>4-12);break;case2:day—;if(day==O)day=31;write_nyr(9,day);write_com(0x80+9);break;case3:month—;if(month==0)month=12;write_nyr(6,month);write_com(0x80+6);break;case4:year—;if(year==-l)year=99;write_nyr(3,year);write_com(0x80+3);break;})})if(s4==0)〃检测S4{delay(5);if(s4==0){flagl=*flagl;while(!s4);di();if(flagl==O){〃退出闹钟设置时保存数值flag=O;write_com(0x80+0x40);write_date(**);write_date(**); 102write_com(0x0c);write_ds(l,miao);write_ds(3,fen);write_ds(5,shi);)else{〃进入闹钟设置read_alarm();〃读取原始数据miao二amiao;〃重新赋值用以按键调节fen=afen;shi=ashi;write_com(0x80+0x40);write_date(R);/Z显示标志write_date(T);write_com(0x80+0x40+3);write_sfm(4,ashi);/ノ送液晶显示闹钟时间write_sfm(7,afen);write_sfm(10,amiao);))voidwrite_ds(ucharadd,uchardate){〃写12c887函数dscs=0;dsas=l;dsds=1;dsrw=1;P0二add”先写地址dsas=O;dsrw=0;P0=dale;〃再写数据dsrw=1;dsas=l;dscs=l;}ucharread_ds(ucharadd)(〃读12c887函数uchards_date;dsas=l;dsds=l;dsrw=1;dscs=O;P0二add;〃先写地址dsas=O;dsds=O;PO=Oxff; 103ds_date二PO;〃再读数据dsds=l;dsas=l;dscs=l;returnds_date;/*---首次操作12c887时给予寄存器初始化…voidset_time(){/Z首次上电初始化时间函数write_ds(0,0);write_ds(1,0);write_ds(2,0);write_ds(3,0);write_ds(4,0);write_ds(5,0);write_ds(6,0);write_ds(7,0);write_ds(8,0);write_ds(9,0);}サvoidread_alarm(){〃读取12C887闹钟值amiao=read_ds(1);afen=read_ds(3);ashi=read_ds(5);}voidmain()〃主函数(init();〃调用初始化函数while(l)(keyscan();〃按键扫描if(fla[ri=l)〃当闹钟中断时进入这里(di();delay(lOO);di();delay(500);)if(flag==O&&flagl==O)〃正常工作时进入这里keyscan。;〃按键扫描year=read_ds(9);〃读取!2C887数据month=read_ds(8);day=read_ds(7);week=read_ds(6); 104shi=read_ds(4);fen=read_ds(2);miao=read_ds(0);write_sfm(10,miao);〃送液晶显示write_sfm(7,fen);write_sfm(4,shi);write_week(week);write_nyr(3,year);write_nyr(6,month);write_nyr(9,day);)})voidexter()interrupt2〃タト部中断1服务程序{ucharc;〃进入中断表示闹钟时间到,ルれ日ニ1;〃设置标志位,用以大程序中报警提示c=read_ds(0x0c);〃读取!2C887的C寄存器表示响应了中断)以下是define.h源代码(P340)#defineucharunsignedchar#defineuintunsignedintsbitdula=P2A6;sbitwela=P2A7;sbitrs=P3A5;sbitlcden=P3A4;sbitsl=P3A〇;〃功能键sbits2=P3A1;〃增加键sbits3=P3A2;〃减小键sbits4=P3A6;〃闹钟查看键sbitrd=P3A7;sbitbeep=P2A3;〃蜂鸣器sbitdscs=P1A4;sbitdsas=PlA5;sbitdsrw=PlA6;sbitdsds=PlA7;sbitdsirq=P3A3;bitflagl,flag_ri;〃定义两个位变量ucharcount,slnum,flag,tO_num;〃其它变量定义charmiao,shi,Pen,year,month,day,week,amiao,afen,ashi;ucharcodetableロメ20--“,液晶固定显示内容ucharcodetable1[]=*'::"; 105voidwrite_ds(uchar,uchar);〃函数申明voidset_alarm(uchar,uchar,uchar);voidread_alarm(); 106ucharread_ds(uchar);voidset_time();程序16.3.1使用TX-1C实验板上的DS18B20温度传感器设计温控系统C语言源代码(part4.3P349)#include 107bittempreadbit(void)〃读1位函数(uinti;bitdat;ds=0;i++;〃i++起延时作用ds=l;i++;i++;dat=ds;i=8;while(i>0)i—;return(dat);}uchartempread(void)〃读!个字节(uchari,j,dat;dat=O;fbr(i=l;i<=8;i++){j=tempreadbit();dat=(j«7)l(dat»l);〃读出的数据最低位在最前面,这样刚好一个字节在DAT里}return(dat);)voidtempwritebyte(uchardat)〃向18B20写ー个字节数据(uinti;ucharj;bittestb;for(j=l;j<=8;j++)(testb=dat&0x01;dat=dat»1;if(testb)〃写1ds=0;i++;i++;ds=l;i=8;while(i>0)i—;)else{ds=0;〃写0i=8;while(i>0)i—;ds=l;i++;i++;)voidtempchange(void)//DS18B20开始获取温度并转换(dsreset();delay(l);tempwritebyte(Oxcc);/Z写跳过读ROM指令 108tempwritebyte(0x44);/Z写温度转换指令uintget_temp()〃读取寄存器中存储的温度数据(uchara,b;dsreset();delay(l);tempwritebyte(Oxcc);tempwritebyte(Oxbe);a=tempread();〃读低8位b=tempread()J〃读高8位temp=b;temp«=8;〃两个字节组合为1个字temp=templa;f_temp=temp*0.0625;〃温度在寄存器中为12位分辨率位0.0625°temp=Ltemp*10+0.5;〃乘以10表示小数点后面只取1位,加0.5是四舍五入Ctemp=Ltemp+0.05;returntemp;//temp是整型〃〃〃〃〃ル〃〃〃/显示程序〃〃〃〃〃〃〃〃〃〃〃〃〃voiddisplay(ucharnum,uchardat)(uchari;dula=O;PO=table|dat];dula=l;dula=O;wela=0;i=0XFF;i=i&(-<(0X0l)«(num)));P0=i;wela=l;wela=0;delay(1);)voiddis_temp(uintt)(uchari;三t/100;display(Oj);i=t%100/10; 109display(l,i+10);i=t%100%10;display(2,i);}llllllllllllllllllllllllllllllllllllllllllllllvoidwam(uints,ucharled)〃蜂鸣器报警声音,s控制音调(uchari;i=s;dula=0;wela=0;beep=0;Pl=-(led);while(i-)(dis_temp(get_temp());)beep=1;Pl=0XFF;i=s;while(i—)(dis_temp(get_temp());}}voiddeal(uintt){uchari;if((t>wam」2)&&(lv二warn」l))〃大于25度小于27度{wam(40,0x01);elseif(t<=warn_12)〃小于25度|wam(10,0x03);)elseif((tvwarn_h2)&&(t>=warn_hl))〃小于32度大于30度(wam(40,0x04);)elseif(t>=wam_h2)〃大于32度(wam(10,0x0c);} 110else(i=40;while(i—)(dis_temp(get_temp());voidinit_com(void)(TMOD=0x20;PCON=0x00;SCON=0x50;TH1=0xFd;TL1=OxFd;TRI=1; 111voidcomm(char*parr)(do(SBUF〃发送数据while(!TI);等待发送完成标志为1TI〃标志清零}while(*parr);保持循环直到字符为、。’=*parr++;//=0;//voidmain()(ucharbuff[4],i;dula=O;wela=0;init_com();while(l)(tempchange();for(i=10;i>0;i—){dis_temp(get_temp());}deal(temp);sprintf(buff,M%r,Ltemp);for(i=10;i>0;i-)(dis_temp(get_temp());}comm(buff);for(i=10;i>0;i-)(dis_temp(get_temp());}))程序17.3.1太阳能充/放电控制器C语言源代码(part4.4P362)主程序代码controller.c#include 112#include 113pwm_l();〃打幵充电cdd=O;〃打开充电指示)fcd_z();〃按键检测fcdJO;func();diqynum—;if(diqynum>0)〃报警指示(didi(3);delay(1000);)elsediqynum=l;}didi(l);〃欠压恢复时开启负载fz_on;delay(l);fzd=O;PlM0=0x8f;//00000111PlMl=0xcl;//00000111flag_fz=l;delay(lOOO);qyd=l;pwm_a=20;)if(v_temp>=qy&&v_temp<=gygd){〃正常工作电压区间qyd=l;〃欠压指示关闭if(v_temp 114if(v_temp 115fzd=l;flag_fz=O;while(!(Ad_Av(1)<=gyhf)){〃等待过压恢复fcd_z();〃按键检测fcdj();func();digynum—;if(digynum>0)〃报警指示{didi(3);delay(lOOO);}elsedigynum=l;)didi(l);fz_on;〃过压恢复时开启负载delay(l);fzd=O;PlM0=0x8f;//00000111PlMl=0xcl;//00000111fla&_fz=l;delay(lOOO);gyd=l;}}checkpv〇;〃检测电池板电压checkgz();〃检测过载状态fcd_z();〃按键检测fcdj();func(););源代码为pvgz.h(P366)voidpwm_zk(uchargao){〃脉宽调制gao为高电平持续时间最大255,最小1PCA_PWM0=0;CCAP0H=(256-gao);CR=1;}voidpwm_l()〃PWM端固定高电平(PCA_PWM0=0;CCAP0H=0;)voidpwm_0()//PWM端固定低电平(PCA_PWM0=0x03; 116CCAP0H=0xff;)voidcheckpv()〃检测电池板电压(〃省去检测电池板程序voidcheckgz()floattemp_gz;if(flag_fz==l)(temp_gz=Ad_fu(4);if(temp_gz>gzdy){〃判断是否过载注意:只有在前面过程负载打开的情况下〃方可判断负载是否过载,否则将不做判断。PlM0=0x87;//00000111PlMl=0x49;fz_off;didi(l);flag_fz=0;fzd=l;flag_gz=l;flag_tlgz=0;}if(temp_gz>(gzdy-0.02)){〃快过载前的报警提示didi(l);))〃这里省去过载恢复检测程序源代码为writeyejing.h(P367)voidfcd_z()(if(keyl==0){delay(20);if(keyl=0){while(!keyl);switch(flag_fun)( 117case0:fcd+=0.01;cwfc+=0.01;sectorerase(0x2e00);〃擦除ROM的最后一个扇区write_eep(cwfc,0x2e00);〃存储改变后的数据byte_write(0x2e06,1);break;case1:gzdy=gzdy+0.01;seclorerase(0x2c00);〃擦除ROM的倒数第二个扇区byte_write(0x2c00,gzdy*10〇);〃存储改变后的数据byte_write(0x2c06,1);break;case2:break;case3:〃按下这里所有设计还原出厂默认gzdy=0.13;fcd=13.7;cwfc=13.7;sectorerase(Ox2e00);sectorerase(Ox2cOO);break;)didi(l);)))voidfcdj()(if(key2=0)(delay(20);if(key2=0){while(!key2);switch(flag_fun)(case0:fcd-=0.01;cwfc-=0.01;sectorerase(Ox2eOO);〃擦除ROM的最后一个扇区write_eep(cwfc,0x2e00);〃存储改变后的数据byte_write(0x2e06,1);break;case1: 118gzdy二gzdy-0.01;sectorerase(Ox2cOO);〃擦除ROM的倒数第二个扇区byte_write(0x2c00,gzdy*10〇);〃存储改变后的数据byte_write(0x2c06,1);break;case1:break;case2:break;)didi(l);)voidfunc()(ucharkey_flag=O;if(key3==O){delay(20);if(key3==O)(while(!key3);flag_fun++;if(flag_fun=2)〃直至リ调节完毕方可退出这里(didi(3);while(key_flag=O){if(keyl==O)(delay(20);if(keyl=O){while(ikeyl);fcd+=O.Ol;cwfc+=0.01;)didi(l);}if(key2=0)(delay(20);if(key2==O){while(!key2);fcd-=O.Ol;cwfc-=0.01;didi(l); 119)if(key3==0)(delay(20);if(key3=0){while(!key3);flag_fun++;sectorerase(Ox2eOO);〃擦除ROM的最后一个扇区write_eep(cwfc,0x2e00);//存储改变后的数据byte_write(0x2e06,l);key_flag=l;})if((Ad_Av(l)>(fcd-0.0l))&&(Ad_Av(l)<(fcd+O.Ol)))didi(l);〃电源校准后报警提示})if(flag_fun=4)flag_fun=O;switch(flag_fun)(caseO:didi(l);break;casel:didi(2);break;case2:didi(3);break;case3:beep=l;delay(2OOO);beep=O;break;)源代码为init.h(P370)voiddidi(uchardi_num){〃蜂鸣器响儿次由di_num决定uchara; 120fbr(a=di_num;a>O;a-)(beep=1;delay(400);beep=O;delay(400);})voidinit()(qyd=l;〃指示灯初始化gyd=i;cdd=l;fzd=l;zcd=l;beep=0;czfz=li〃负载关闭czcf=0;〃关闭充电diqynum=0;digynum=0;flag_pv=0;flag_fun=O;flag_tl=O;flag_gz=O;flag_tlgz=O;pwm_num=2;pwm_a=30;fcd=13.7;cwfc=13.7;dwfc=14.1;gwfc=13.3;gzdy=0.45;〃设定负载过载电压为0.45Vcd_off;tl_num=0;tl_numgz=0;PlM0=0x87;PIM1=0x49;fz_off;delay(l);PlM0=0x8f;PlMl=0x41;didi(l);delay(6000);if(byte_read(0x2e06)==l)〃当改变过浮充电压点后重新读取 121cwfc=read_eep(0x2e00);fcd=cwfc;)if(byte_read(0x2c06)==l)〃当改变过浮充电压点后重新读取(gzdy=byte_read(0x2c00)/100.0;)TMOD=Oxl2;IP=0x08;TH0=(256・U5);〃定时器初始化周期为U5US,PWM频率为34HzTL0=(256-115);THl=(65536・50000)/256;〃定时器初始化TL1=(65536-50000)%256;ET0=l;ET1=1;TR1=1;TR0=l;〃设置为PWM输出方式////PWM计数器初值清0EA=1;CMOD=0x04;CCAPM0=0x42;CL=0;CH=0;ADC_CONTRI=OxeO;〃打开AD电源PlMO=Ox87;P1M1=0x49;fz_on;delayus(5);flag_fz=l;fzd=0;PlM0=0x8f;〃设置为AD采样模式PlMl=0x41;didi(l);checkgz();checkpv();}voiddelay(uintx)〃延时为1ms的整数倍,由x决定(uinty,z;for(y=x;y>0;y—)for(z=110;z>0;z—);)voiddelayus(ucharx)〃延时为lus的整数倍,由x决定uchary;fbr(y=x;y>O;y-);)源代码为ad.h:(P372) 122floatGetAD(ucharchannel)〃用户函数(unsignedcharAD_finished=O;floattad_val;tad_val=0;ADC_CONTRI=(channel-l);〃选择AD端u号ADC_DATA=0;ADC_LOW2=0;ADC_CONTRI=0x08;〃启动AD转换while(AD_finished=O){AD_finished=(ADC_CONTR&Ox10);}tad_val=(ADC_DATA*4+ADC_LOW2);ADC_CONTR&=OxeO;return(tad_val);}floatAd_Av(ucharchan){〃求蓄电池电压平均值floatVal_Av;ucharnum;Val_Av=0;fbr(num=120;num>0;num-){Val_Av+=GetAD(chan);)Val_Av/=120.0;Val_Av=Val_Av*l5.0/1024;return(Val_Av);}floatAd_fu(ucharchan){〃求其它电压平均值floatVal_Av;ucharnum;Val_Av=0;fbr(num=5;num>0;num—)Val_Av+=GetAD(chan); 123)Val_Av/=5.0;Val_Av=Val_Av*5.0/l024;return(Val_Av);#defineqy#defineqyhf#definefcdy#definegddy#definegyhf#definegygd#definepvbt#definejcjg#definejcgzjg#definefz_on#definefz_off#definecd_on#definecd_offsbitczfz=PlA3;sbitczcf=P3A7;sbitbeep=P1A6;sbitrs=PlA7;sbitlcden=PlA4;sbitqyd=P2A2;sbitgyd=P2A3;sbitfzd=P2A4;sbitcdd=P2A5;sbitzcd=PlA5;sbitkeyl=P3A2;sbitkey2=P3A3;sbitkey3=P3A4;voiddelay(uint);voiddelayus(uchar);voiddidi(uchar);源代码为define.h(P373)#defineuintunsignedint#defineucharunsignedcharfcd-2.9//10.8〃欠压fcd-0.5//13.2〃欠压恢复fcd-0.128//13.2〃浮充电压fcd+0.128〃13.456〃关断电压fcd+0.9〃14.6〃过压恢复fcd+l.l〃14.8//过压关断0.5〃当PV板电压大于电池IV左右时オ可允许充电1200〃此数・50ms总和为检测电池板与过载恢复检测间隔时间单位(S)100〃过载后检测负载恢复间隔czfz=0〃打开负载czfz=l〃关闭负载czcf=l〃开始充电czcf=0〃关闭充电〃控制负载〃控制充电〃蜂鸣器〃液晶数据命令/Z液晶使能〃欠压灯〃过压灯〃负载灯〃充电灯〃系统正常灯〃按键定义voidinit。;〃以下为变量定义uchara,fz,diqynum,digynum,flag_t1gz,flag_gz;ucharflag_t1,flag_pv,flag_fz,pwm_num,tl_numgz;ucharpwm_a,flag_fun;uinttl_num;floatxdatafcd,ad_val,v_temp,cwfc,dwfc,gwfc,gzdy; 124源代码为stc_eeprom.h:(P374)尸externvoidSectorErase(uintsector_addr);/Z扇区擦除externucharbyte_read(uintbyte_addr);//bytei买externvoidbyte_write(uintbyte_addr,ucharoriginal_data);//byte写externucharbyte_write_verify(uintbyte_addr,ucharoriginal_data);〃byte与并校验externucharArrayWrite(uintbegin_addr,uintlen,ucharcode*array);//byte数组写并校验externvoidArrayRead(uintbegin_addr,ucharlen);/Z读出,保存在Ttotal[]中ウ#defineRdCommand0x01#definePrgCommand0x02#defineEraseCommand0x03#defineError1#defineOk0#defineWaitTime0x01#definePerSector512/*============打开!SPJAP功能============*/voidISP_IAP_enable(void)(EA=0;/・关中断・/ISP_CONTR=ISP.CONTR&0xl8;/*0001,1000*/ISP_CONTR=ISP.CONTRIWaitTime;/・写入硬件延时・/ISP_CONTR=ISP.CONTR10x80;/*ISPEN=1*/}/*==========关闭ISPJAP功能============*/voidISP_IAP_disable(void)(ISP_CONTR=ISP.CONTR&0x7f;/*ISPEN=0*/ISP.TRIG=0x00;EA=1;/・开中断・/}/*===========公用的触发代码=============*/voidISPgoon(void)ISP_IAP_enable();/・打开!SPJAP功能・/ISP_TRIG=0x46;/・触发!SPJAP命令字节1*/ISP_TRIG=0xb9;/・触发ISP_IAP命令字节2*/__nop_(); 125/*============字节读=================*/unsignedcharbyte_read(unsignedintbyte_addr)(ISP_ADDRH=(unsignedchar)(byte_addr»8);/・地址赋值・/ISP_ADDRL=(unsignedchar)(byte_addr&OxOOff);/・清除低3位・//・写入读命令・/ISP_CMD=ISP_CMD&Oxf8;ISPgoon();/・触发执行・/ISP_IAP_disable();/・关闭ISP.IAP功能*/return(ISP_DATA);/・返回读到的数据・/ISP_CMD=ISP_CMDIRdCommand;voidsectorerase(unsignedintsector_addr)(unsignedintiSectorAddr;iSectorAddr=(sector_addr&OxfeOO);/・取扇区地址・/ISP_ADDRH=(unsignedchar)(iSectorAddr»8);ISP_ADDRL=0x00;ISP.CMD=ISP.CMD&Oxf8;/・清空低3位・/ISP.CMD=ISP.CMDIEraseCommand;/・擦除命令3*/ISPgoon();ISP_IAP_disable();/*触发执行・//*关闭ISP,IAP功能・//*====================字节写========================*/voidbyte_write(unsignedintbyte_addr,unsignedcharoriginal_data)(ISP_ADDRH=(unsignedchar)(byte_addr»8);/・取地址・/ISP_ADDRL=(unsignedchar)(byte_addr&OxOOff);ISP.CMD=ISP.CMD&0xf8;/・清低3位・/ISP_CMD=ISP_CMDIPrgCommand;/*写命令2*/ISP_DATA=original_data;/・写入数据准备・/ISPgoon();/・触发执行・/ISP_IAP_disable();/・关闭IAP功能*/)voidwrite_eep(floateep_data,uintadd)ucharfcdh,fcdl;fcdh=(uint)(eep_data*100)/256;fcdl=(uint)(eep_data*l00)%256;byte_write(add,fcdh)ル写入浮充电电压高8位 126byte_write(add+l,ficdl);〃写入浮充电电压低8位}floatread_eep(uintadd){floatdate_re;uchardateh,datel;dateh=byte_read(add);datel=byte_read(add+1);date_re=(dateh*256+datel)/l00.0;returndate_re;1源代码为STC12C5410ad.h:(P376)/*AfterisSTCadditionalSFRorchange*//*sfrAUXR=0x8e;*//*sfrIPH=0xb7;*//*WatchdogTimerRegister*/sfrWDT_C0NTR=0xel;/*ISP_IAP_EEPROMRegister*/sfrISP_DATA=0xe2;sfrISP_ADDRH=0xe3;sfrISP.ADDRL=0xe4;sfrISP_CMD=0xe5;sfrISP_TRIG=0xe6;sfrISP_CONTR=Oxe7;/*SystemClockDivider*/sfrCLK_DIV=0xc7;/*I_OPortModeSetRegister*/sfrP0M0=0x93;sfrPOM1=0x94;sfrPlM0=0x91;sfrPIMl=0x92;sfrP2M0=0x95;sfrP2Ml=0x96;sfrP3M0=0xbl;sfrP3Ml=0xb2;/*SPIRegister*/sfrSPSTAT=0x84;sfrSPCTL=0x85;sfrSPDAT=0x86;/*ADCRegister*/sfrADC_CONTR=0xc5;sfrADC_DATA=0xc6;sfrADC_LOW2=Oxbe; 127/*PCASFR*/sfrCCON=0xD8;sfrCMOD=0xD9;sfrCCAPM0=0xDA;sfrCCAPM1=0xDB;sfrCCAPM2=0xDC;sfrCCAPM3=0xDD;sfrCCAPM4=OxDE;sfrCCAPM5=OxDF;sfrCL=0xE9;sfrCCAP0L=0xEA;sfrCCAP!L=OxEB;sfrCCAP2L=0xEC;sfrCCAP3L=0xED;sfrCCAP4L=0xEE;sfrCCAP5L=0xEF;sfrCH=0xF9;sfrCCAPOH=OxFA;sfrCCAP!H=OxFB;sfrCCAP2H=OxFC;sfrCCAP3H=0xFD;sfrCCAP4H=OxFE;sfrCCAP5H=OxFF;sfrPCA_PWM0=0xF2;sfrPCA_PWMl=0xF3;sfrPCA_PWM2=0xF4;sfrPCA_PWM3=0xF5; 128sfrPCA_PWM4=0xF6;sfrPCA_PWM5=0xF7;/*CCONsbitCFsbitCRsbitCCF5sbitCCF4sbitCCF3sbitCCF2sbitCCF1sbitCCFOサ=CCONA7;=CCONA6;=CCONA5;=CCONA4;=CCONA3;=CCONA2;=CCONA1;=CCONA0;/*AboveisSTCadditionalSFRorchange*/REG51F.HHeaderfilefor8xC31/51,80C51Fx,80C51Rx+Copyright(c)1988-1999KeilElektronikGmbHandKeilSoftware,Inc.Allrightsreserved.ModificationaccordingtoDatasheetfromApril1999-SFR'sAUXRandAUXR1addedfor80C51Rx+derivatives刃/*BYTERegisters*/sfrP0=0x80;sfrPl=0x90;sfrP2=OxAO;sfrP3=OxBO;sfrPSW:=OxDO;sfrACC:=OxEO;sfrB=OxFO;sfrSP=0x81;sfrDPL==0x82;sfrDPH:=0x83;sfrPCON==0x87;sfrTCON:=0x88;sfrTMOD=0x89;sfrTLO=:0x8A;sfrTLl=:0x8B;sfrTHO==0x8C; 129sfrTHl=0x8D;sfrIE=OxA8;sfrIP=0xB8;sfrSCON=0x98;sfrSBUF=0x99;/*80C51Fx/RxExtensions*/sfrAUXR=0x8E;/*sfrAUXRl=0xA2;*/sfrSADDR=OxA9;sfrIPH=0xB7;sfrSADEN=0xB9;sfrT2CON=0xC8;sfrT2MOD=0xC9;sfrRCAP2L=0xCA;sfrRCAP2H=0xCB;sfrTL2=0xCC;sfrTH2=OxCD;/*BITRegisters*//*PSW*/sbitCY=PSWA7;sbitAC=PSWA6;sbitFO=PSWA5;sbitRS1=PSWA4;sbitRSO=PSWA3;sbitOV=PSWA2;sbitP=PSWA0;/*TCON*/sbitTF1=TCONA7;sbitTRI=TCONA6;sbitTFO=TCONA5;sbitTRO=TCONA4;sbitIE1=TCONA3;sbitIT1=TCONA2;sbitIEO=TCONA1;sbitITO=TCONA0;/*P3*/sbitRD=P3A7;sbitWR=P3A6;sbitTl=P3A5; 130sbitTO=P3A4;sbitINTI=P3八3;sbitINTO=P3八2;sbitTXD=P3A1;sbitRXD=P3AO;/*SCON*/sbitSMO=SCONA7;//alternatively“FE”sbitFE=SCONA7;sbitSMI=SCONA6;sbitSM2=SCONA5;sbitREN=SCONA4;sbitTB8=SC0NA3;sbitRB8=SCONA2;sbitTI=SCONA1;sbitRI=SCONA0;sbitT2EX=P1A1;sbitT2=P1AO;/*T2CON*/sbitTF2=T2CONA7;sbitEXF2=T2CONA6;sbitRCLK=T2CONA5;sbitTCLK=T2CONA4;sbitEXEN2=T2CONA3;sbitTR2=T2CONA2;sbitC_T2=T2CONA1;sbitCP_RL2=T2CONA0;/*PCAPin*/sbitCEX3=P2A4;sbitCEX2=P2AO;sbitCEX1=P3A5;sbitCEXO=P3A7;sbitECI=P3A4;/*IE*/sbitEA=IEA7;sbitEPCA_LVD=IEA6;sbitEADC_SPI=IEA5;sbitES=IEA4; 131sbitET1=IEA3;sbitEX1=IEA2;sbitETO=IEAI;sbitEXO=IEA〇;/*IP*/sbitPPCA_LVD=]p%sbitPADC_SPI=IPA5;sbitPS=1PA4;sbitPT1=圧へ3;sbitPX1=IPA2;sbitPTO=IPA];sbitPXO=IPAO;ISD400X系列语音芯片C语言参考程序:抽被2P425)#include 132cs_4004=0;m=0x30;for(i=0;i<8;i++)(m=_cror_(m,l);j=m«l;mosi_4004=CY;sclk_4004=0;sclk_4004=1;)cs_4004=1;}voidpowerdown()〃下电(unsignedcharm,i,j;cs_4004=l;sclk_4004=0;cs_4004=0;m=0xl0;for(i=0;i<8;i++)(m=_cror_(m,1);j=m«1;mosi_4004=CY;sclk_4004=0;sclk_4004=l;}cs_4004=l;)voidpowerup()/Z上电{unsignedcharm,i,j;cs_4004=l;sclk_4004=0;cs_4004=0;m=0x20;for(i=0;i<8;i)m=_cror_(m,l);j=m«1;mosi_4004=CY;sclk_4004=0;sclk_4004=l;} 133cs_4004=1;}voidrecord4004(unsignedintaddress){/Z录音addressー录音地址〇一2400unsignedchari,m,j;unsignedintdatasoute=0;powerupO;delay(5U8);〃ヒ电延时powerupO;delay(5118)ル上电延时delay(5U8);〃上电延时cs_4004=l;sclk_4004=0;m=0xa0;cs_4004=0;for(i=0;i<16;i++){address=_iror_(address,1);datasoute=address«1;mosi_4004=CY;sclk_4004=0;sclk_4004=1;}for(i=0;i<8;i++)(m=_cror_(m,l);j=m«1;mosi_4004=CY;sclk_4004=0;sclk_4004=1;)cs_4004=l;sclk_4004=0;m=0xb0;cs_4004=0;for(i=0;i<8;i++){m=_cror_(m,l);j=m«l;mosi_4004=CY; 134sclk_4004=0;sclk_4004=l;}cs_4004=l;PO=Oxff;datasoute=0;while(im_4004==1)〃存储地址换行标志(if(rac_4004)〃记录本次录音所占的行数(也就是本次录音有多大)(delay(20000);datasoute-H-;}〃在这里应该加上自己的程序,就是录音退出程序}}//whileend;voidaudioout(unsignedintaddress)〃放音程序(unsignedchari,m,j;unsignedintdatasoute;powerupO;cs_4004=l;sclk_4004=0;cs_4004=0;m=0xe0;for(i=0;i<16;i++){address=_iror_(address,1);datasoute=address«1;sclk_4004=0;mosi_4004=CY;scIk_4004=l;}for(i=0;i<8;i++)(m=_cror_(m,l);j=m«l;sclk_4004=0;mosi_4004=CY;sclk_4004=1;}cs_4004=l;sclk_4004=0;m=0xf0; 135cs_4004=0;for(i=0;i<8;i)(m=_cror_(m,l);j=m«l;sclk_4004=0;mosi_4004=CY;sclk_4004=l;}cs_4004=l;PO=Oxff;while(int_4004==1)voidmain()(record4004(0);audioout(O);while(l);例21.1.1使用TX-1C实验板上两个独立按键调节直流电机的转速,同时在实验板的数码管上象征性的显示相应的转速值。通过控制单片机输出不同占空比的PWM信号来控制直流电机的转速(感性认识)。(part5.3P434)#include 136ucharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};voiddelay(uchari)〃延时函数{ucharj,k;for(j=i;j>0;j-)for(k=125;k>0;k—);}voiddisplayO〃数码管显示函数(dula=0;P0=table[show_num];dula=l;dula=0;wela=0;P0=0xfe;wela=l;wela=0;delay⑸;PO=table[OJ;dula=l;dula=0;PO=Oxfd;wela=l;wela=0;delay⑸;P0=table[0];dula=l;dula=0;P0=0xfb;wela=l;wela=0;delay(5);PO=table[OJ;dula=l;dula=0;P0=0xf7;wela=l;wela=0;delay(5);)voidkey()〃按键检测处理函数(if(jia_key==O){delay(5);〃消抖if(jia_key==O)(num++;〃加速健按下,速度标志加1if(num==4)num=3;〃已经达到最大3,则保持while(jia_key==O),等待按键松开if(jian_key==O) 137(delay⑸;if(jian_key==O){if(num!=0)〃减速键按下,速度标志减1num—;elsenum=0;〃已经达到最小0,则保持while(jian_key=0);voiddispose()〃根据速度标志进行数据处理(switch(num)(case0:show_num=l;〃数码管第一位显示的数据gao_num=l;//PWM信号中高电平持续时间标志为1di_num=3;〃PWM信号中低电平持续时间标志为3,此时速度最慢break;case1:show_num=2;gao_num=2;di_num=2;break;case2:show_num=3;gao_num=3;di_num=l;break;case3:show_num=4;gao_num=4;di_num=O;〃此时速度最快break;})voidqudong()〃控制电机程序(uchari;if(di_num!=0)(for(i=0;i 138dianji=0;〃实现PWM信号低电平输出display();〃利用显示函数起延时作用,这样也不影响数码管显示,ー举两得)}fbr(i=0;i 139qudongO;例2121步进电机应用C语言程序设计(part3.2P444)#include 140)voidkey()〃按键检测处理函数{if(jia_key==O){delay(5);〃加速键按下,消抖if(jia_key==O)(num++;〃速度标示加1if(num==4)num=3;〃达到最大3则保持while(jia_key==O);〃等待松开按键)}if(jian_key==O)(delay(5);〃减速键按下if(jian_key==O){if(num!=0)num-;〃速度标示减1elsenum=0;〃达到最小〇则保持while(jian_key=0);if(zf_key==O)(delay(5);〃正反转按键按下if(zfLkey==O)(flag二〜flag;〃正反转标识取反while(zf_key==0);}voiddispose()〃根据速度标识进行数据处理(switch(num)(case0:show_num=2;〃数码管第一位显示的数字maichong=5;〃利用maichong数据控制送给电机脉冲的频率,控制速度break;case1:show_num=4;maichong=4;break;case2:show_num=6;maichong=3;break;case3:show_num=8;maichong=2; 141break;)if(flag==O)(table_begin=O;//flag为〇,正转)elsetable_begin=4;//flag为1,反转voidqudong()〃电机速度,和正反转控制(uchari,j;fbr(j=0+table_begin;jv4+table_begin;j++)(Pl=tablel|j];〃读取控制电机转动!/O口表for(i=0;i 142voidmain()(while(l)key。;dispose();qudong();)例21.3.1舵机应用C语言程序设计实例:开机时舵机角度自动转为O度,通过实验板上的独立按键调节舵机的角度转动,并且在实验板数码管上显示相应的角度。本例仅演示5个角度的控制,若想实现任意角度控制请大家自行编程实验。程序代码如下:(part5.3P453)〃调节舵机使之转动5个角度〇4590135180PWM信号周期为20ms,〃控制高电平的持续时间即可控制舵机停止制动的角度,0.5ms-0度!-451.5-902-1352.5-180#includeureg52.hnunsignedcharcount;sbitpwm=P3A0;sbitjia=P3A7;sbitjan=P3A6;unsignedcharjd;〃程序流程是:开机时舵机角度自动转为〇度,按下P3.7则转到45度,以后就根据两个按键的按下而转动//0.5ms次数标识//PWM信号输出〃角度增加按键检测IOロ〃角度减少按键检测IOロ//角度标识 143voiddelay(unsignedchari)〃延时(unsignedcharj,k;for(j=i;j>0;j-)for(k=125;k>O;k—);voidTimeO_Init()〃定时器初始化1TMOD=0x01;IE=0x82;THO=Oxfe;TLO=0x33;〃定时器。工作在方式1//11.0592MZ晶振,0.5msTRO=1;〃定时器开始voidTimeO_Int()interrupt1〃中断程序THO=Oxfe;TLO=0x33;〃甫新赋值if(count 144(jd-;〃角度标识减1count=0;if(jd==O)jd=l;〃已经是〇度,则保持while(jan==O);)voidmain()(jd=l;count=0;TimeO」nit();whiled)(keyscan();〃按键扫描}
此文档下载收益归作者所有