TLC549完整C51程序
- 格式:doc
- 大小:35.00 KB
- 文档页数:3
MCS-51单片机实用子程序库内容目前已有若干版本的子程序库公开发表,它们各有特色。
本程序库中的开平方算法为快速逼近算法,它能达到牛顿迭代法同样的精度,而速度加快二十倍左右,超过双字节定点除法的速度。
本子程序库对《单片机应用程序设计技术》一书附录中的子程序库作了重大修订:(1)按当前流行的以IBM PC 为主机的开发系统对汇编语言的规定,读者不必再进行修改,便可直接使用。
(2)对浮点运算子程序库进行了进一步的测试和优化,对十进制浮点数和二进制浮点数的相互转换子程序进行了彻底改写,提高了运算精度和可靠性。
(3)新增添了若干个浮点子程序(传送、比较、清零、判零等),使编写数据处理程序的工作变得更简单直观。
在使用说明中开列了最主要的几项:标号、入口条件、出口信息、影响资源、堆栈需求,各项目的意义请参阅《单片机应用程序设计技术》第六章6.3.7 节的内容。
程序清单中开列了四个栏目:标号、指令、操作数、注释。
为方便读者理解,注释尽力详细。
子程序库的使用方法如下:1.将子程序库全部内容链接在应用程序之后,统一编译即可。
优点是简单方便,缺点是程序太长,大量无关子程序也包含在其中。
2.仅将子程序库中的有关部分内容链接在应用程序之后,统一编译即可。
有些子程序需要调用一些低级子程序,这些低级子程序也应该包含在内。
优点是程序紧凑,缺点是需要对子程序库进行仔细删节。
(一)MCS-51定点运算子程序库及其使用说明定点运算子程序库文件名为DQ51.ASM,为便于使用,先将有关约定说明如下:1.多字节定点操作数:用[R0]或[R1]来表示存放在由R0或R1指示的连续单元中的数据。
地址小的单元存放数据的高字节。
例如:[R0]=123456H,若(R0)=30H,则(30H)=12H,(31H)=34H,(32H)=56H。
2.运算精度:单次定点运算精度为结果最低位的当量值。
3.工作区:数据工作区固定在PSW、A、B、R2~R7,用户只要不在工作区中存放无关的或非消耗性的信息,程序就具有较好的透明性。
第1章C51数据类型与运算1.1C51数据类型C51的数据类型如下所示:C51编译器支持的数据类型、长度和值域如下表1-1所示。
与面向数学运算的计算机相比,51单片机对变量类型或数据类型的选择更具有关键性意义。
如果在程序设计中使用大量而不必要的变量类型,这会导致C编译器调用库函数的数量,以处理大量的变量类型和数据类型。
所以必须特别慎重地进行变量和数据类型的选择。
1.2C51数据存储类型C51编译器还可以通过将变量、常量定义成不同的存储类型(data,bdata,idata,pdata,xdata,code)的方法,将它们定义在不同的存储区中。
存储类型与51单片机实际存储空间的对应关系如表1-2所示。
储区中。
片内RAM是存放临时性传递变量或使用频率较高变量的理想场所。
访问片内数据存储器(data、bdata、idata)比访问片外数据存储器(xdata、pdata)相对快一些,因此可将经常使用的变量置于片内数据存储器,而将规模较大的或不常使用的数据置于片外数据存储器中。
C51存储类型及其大小和值域如表1-3所示。
例如:表1-3 C51存储类型及其大小和值域char data var1; /*字符变量var1被定义为data存储类型,定位在片内RAM中*/bit bdata flags; /*位变量flags被定义为data存储类型,定位在片内RAM中的位寻址区*//*(20H~2FH)*/float idata x,y,z; /*浮点变量x,y,z被定义为idata存储类型,定位在片内RAM中,并只能用间接寻址的方法进行访问*/unsigned int pdata dimension; /*无符号整型变量dimension被定义为pdata存储类型,定位在片外RAM中,并用MOVX @Ri访问*/ unsigned char xdata vector[10][4][4]; /*无符号字符三维数组变量vector[10][4][4]被定义为xdata存储类型,定位在片外RAM中,占据10×4×4=160个字节空间*/如果在变量定义时省略存储类型标志符,编译器会自动默认存储类型。
以下程式,为T8试烧台的控制程式:器件有六位数码管显示、报警器、和控制交流接触器的12V继电器。
#include <reg52.h>#define uint unsigned int#define uchar unsigned charsbit set=P3^0; //设置时间,按一下相应的位闪烁;sbit jia=P3^3; //设置位按一下加1;sbit jian=P3^6; //设置位按一下减1;sbit go=P3^1; //功能启动按钮;sbit relay1=P2^7; //控制功率;sbit relay2=P2^6; //控制警报;sbit relay3=P2^5; //控制功率;sbit relay4=P2^4; //控制警报;uchar code table[]={ //显示编码0,1,2,3,4,5,6,7,8,9,-,H,E,L,U,R~0x3f,~0x06,~0x5b,~0x4f,~0x66,~0x6d,~0x7d,~0x07,~0x7f,~0x6f,~0x40,~0x76,~0x79,~0x38,~0x3e,~0x77,~0x49,~0x79,~0x38,~0x3f};uchar fen,miao,t0,t1,t2,set_flag,set_wei_flag,jia_flag,jian_flag,go_flag;uchar shi_qianwei,shi_baiwei,shi_shiwei,shi_gewei,fen_shiwei,fen_gewei,miao_shiwei,miao_gewei;uchar set_fen,set_miao,shan,shan_over;char set_shi_q,set_shi_b,set_shi_s,set_shi_g,set_fen_s,set_fen_g,set_miao_s,set_miao_g,set_wei;int shi,set_shi,jingbao;void delay(uint z) //延时函数1ms ;{uint t1,y;for(t1=z;t1>0;t1--)for(y=100;y>0;y--);}void MCUinit() //初始化MCU;{P0=0;P1=0;P2=0;P3=0;set=1;jia=1;jian=1;go =1;set_shi_q=0;set_shi_b=0;set_shi_s=0;set_shi_g=0;set_fen_s=0;set_fen_g=0;set_miao_s=0;set_miao_g=0;set_wei=7;set_flag=0;jia_flag=0;jian_flag=0;go_flag=0;shi=0;fen=0;miao=0;t0=0;t1=0;shan=0;jingbao=0;TMOD=0x11; //使能定时器并加入初值TH0=(65536-50000)/256;TL0=(65536-50000)%256;TH1=(65536-50000)/256;TL1=(65536-50000)%256;EA=1;ET0=1;ET1=1;TR1=1;}void setscanf() // 设置函数{while(set_flag==1){if(set_shi<=99){if(set_wei_flag==1) //设置位自左往右循环;{set_wei_flag=0;set_wei--;if(set_wei<1)set_wei=6;}switch(set_wei){case 1:{if(jia_flag==1){jia_flag=0;set_miao_g++;if(set_miao_g>9)set_miao_g=0;}if(jian_flag==1){jian_flag=0;set_miao_g--;if(set_miao_g<0)set_miao_g=9;}//时十位;=============================P0=table[set_shi_s];P1=0x20;delay(1);P0=0xff;//时个位;=============================P0=table[set_shi_g];P1=0x10;delay(1);P0=0xff;//分十位;=============================P0=table[set_fen_s];P1=0x08;delay(1);P0=0xff;//分个位;=============================P0=table[set_fen_g];P1=0x04;delay(1);P0=0xff;P0=table[set_miao_s];P1=0x02;delay(1);P0=0xff;//秒个位;=============================if(shan<20) //数码管闪烁占空比的控制1:1{P0=table[set_miao_g]&0x7f;}elseif(shan>=20){P0=0xff;}P1=0x01;delay(1);P0=0xff;break;}case 2:{if(jia_flag==1){jia_flag=0;set_miao_s++;if(set_miao_s>5)set_miao_s=0;}if(jian_flag==1){jian_flag=0;set_miao_s--;if(set_miao_s<0)set_miao_s=5;}//时十位;=============================P0=table[set_shi_s];P1=0x20;delay(1);P0=0xff;P0=table[set_shi_g];P1=0x10;delay(1);P0=0xff;//分十位;=============================P0=table[set_fen_s];P1=0x08;delay(1);P0=0xff;//分个位;=============================P0=table[set_fen_g];P1=0x04;delay(1);P0=0xff;//秒十位;=============================if(shan<20) //数码管闪烁占空比的控制1:1{P0=table[set_miao_s]&0x7f;}elseif(shan>=20){P0=0xff;}P1=0x02;delay(1);P0=0xff;//秒个位;=============================P0=table[set_miao_g];P1=0x01;delay(1);P0=0xff;break;}case 3:{if(jia_flag==1){jia_flag=0;set_fen_g++;if(set_fen_g>9)set_fen_g=0;}if(jian_flag==1){jian_flag=0;set_fen_g--;if(set_fen_g<0)set_fen_g=9;}//时十位;============================= P0=table[set_shi_s];P1=0x20;delay(1);P0=0xff;//时个位;============================= P0=table[set_shi_g];P1=0x10;delay(1);P0=0xff;//分十位;============================= P0=table[set_fen_s];P1=0x08;delay(1);P0=0xff;//分个位;============================= if(shan<20) //数码管闪烁占空比的控制1:1 {P0=table[set_fen_g]&0x7f;}elseif(shan>=20){P0=0xff;}P1=0x04;delay(1);P0=0xff;//秒十位;============================= P0=table[set_miao_s];P1=0x02;delay(1);P0=0xff;//秒个位;============================= P0=table[set_miao_g];P1=0x01;delay(1);P0=0xff;break;}case 4:{if(jia_flag==1){jia_flag=0;set_fen_s++;if(set_fen_s>5)set_fen_s=0;}if(jian_flag==1){jian_flag=0;set_fen_s--;if(set_fen_s<0)set_fen_s=5;}//时十位;=============================P0=table[set_shi_s];P1=0x20;delay(1);P0=0xff;//时个位;=============================P0=table[set_shi_g];P1=0x10;delay(1);P0=0xff;//分十位;=============================if(shan<20) //数码管闪烁占空比的控制1:1{P0=table[set_fen_s]&0x7f;}elseif(shan>=20){P0=0xff;}P1=0x08;delay(1);P0=0xff;//分个位;=============================P0=table[set_fen_g];P1=0x04;delay(1);P0=0xff;//秒十位;=============================P0=table[set_miao_s];P1=0x02;delay(1);P0=0xff;//秒个位;=============================P0=table[set_miao_g];P1=0x01;delay(1);P0=0xff;break;}case 5:{if(jia_flag==1){jia_flag=0;set_shi_g++;if(set_shi_g>9)set_shi_g=0;}if(jian_flag==1){jian_flag=0;set_shi_g--;if(set_shi_g<0)set_shi_g=9;}//时十位;=============================P0=table[set_shi_s];P1=0x20;delay(1);P0=0xff;//时个位;=============================if(shan<20) //数码管闪烁占空比的控制1:1{P0=table[set_shi_g]&0x7f;}elseif(shan>=20){P0=0xff;}P1=0x10;delay(1);P0=0xff;//分十位;=============================P0=table[set_fen_s];P1=0x08;delay(1);P0=0xff;//分个位;=============================P0=table[set_fen_g];P1=0x04;delay(1);P0=0xff;//秒十位;=============================P0=table[set_miao_s];P1=0x02;delay(1);P0=0xff;//秒个位;=============================P0=table[set_miao_g];P1=0x01;delay(1);P0=0xff;break;}case 6:{if(jia_flag==1){jia_flag=0;set_shi_s++;if(set_shi_s>9){set_shi_b++;set_shi_s=0;}}if(jian_flag==1){jian_flag=0;set_shi_s--;if(set_shi_s<0)set_shi_s=9;}//时十位;============================= if(shan<20) //数码管闪烁占空比的控制1:1 {P0=table[set_shi_s]&0x7f;}elseif(shan>=20){P0=0xff;}P1=0x20;delay(1);P0=0xff;//时个位;============================= P0=table[set_shi_g];P1=0x10;delay(1);P0=0xff;//分十位;============================= P0=table[set_fen_s];P1=0x08;delay(1);P0=0xff;//分个位;============================= P0=table[set_fen_g];P1=0x04;delay(1);P0=0xff;//秒十位;============================= P0=table[set_miao_s];P1=0x02;delay(1);P0=0xff;//秒个位;============================= P0=table[set_miao_g];P1=0x01;delay(1);P0=0xff;break;}}}else //画面‘三9999三’============ if(set_shi>99){if(set_wei>5)set_wei=4;if(set_wei_flag==1){set_wei_flag=0;set_wei--;if(set_wei<2)set_wei=5;}switch(set_wei){case 2:{if(jia_flag==1){jia_flag=0;set_shi_g++;if(set_shi_g>9)set_shi_g=0;}if(jian_flag==1){jian_flag=0;set_shi_g--;if(set_shi_g<0)set_shi_g=5;}//‘三’位;=============================P0=table[16];P1=0x20;delay(1);P0=0xff;//时千位;=============================P0=table[set_shi_q];P1=0x10;delay(1);P0=0xff;//时百位;=============================P0=table[set_shi_b];P1=0x08;delay(1);P0=0xff;//时分位;=============================P0=table[set_shi_s];P1=0x04;delay(1);P0=0xff;//时个位;=============================if(shan<20) //数码管闪烁占空比的控制1:1{P0=table[set_shi_g]&0x7f;}elseif(shan>=20){P0=0xff;}P1=0x02;delay(1);P0=0xff;//‘三’个位;=============================P0=table[16];P1=0x01;delay(1);P0=0xff;break;}case 3:{if(jia_flag==1){jia_flag=0;set_shi_s++;if(set_shi_s>9)set_shi_s=0;}if(jian_flag==1){jian_flag=0;set_shi_s--;if(set_shi_s<0)set_shi_s=9;}//时千位;============================= P0=table[16];P1=0x20;delay(1);P0=0xff;//时百位;============================= P0=table[set_shi_q];P1=0x10;delay(1);P0=0xff;//时分位;============================= P0=table[set_shi_b];P1=0x08;delay(1);P0=0xff;//时个位;============================= if(shan<20) //数码管闪烁占空比的控制1:1 {P0=table[set_shi_s]&0x7f;}elseif(shan>=20){P0=0xff;}P1=0x04;delay(1);P0=0xff;//秒十位;============================= P0=table[set_shi_g];P1=0x02;delay(1);P0=0xff;//秒个位;============================= P0=table[16];P1=0x01;delay(1);P0=0xff;break;}case 4:{if(jia_flag==1){jia_flag=0;set_shi_b++;if(set_shi_b>9)set_shi_b=0;}if(jian_flag==1){jian_flag=0;set_shi_b--;if(set_shi_b<0)set_shi_b=9;}//时十位;=============================P0=table[16];P1=0x20;delay(1);P0=0xff;//时个位;=============================P0=table[set_shi_q];P1=0x10;delay(1);P0=0xff;//分十位;=============================if(shan<20) //数码管闪烁占空比的控制1:1{P0=table[set_shi_b]&0x7f;}elseif(shan>=20){P0=0xff;}P1=0x08;delay(1);P0=0xff;//分个位;=============================P0=table[set_shi_s];P1=0x04;delay(1);P0=0xff;//秒十位;=============================P0=table[set_shi_g];P1=0x02;delay(1);P0=0xff;//秒个位;=============================P0=table[16];P1=0x01;delay(1);P0=0xff;break;}case 5:{if(jia_flag==1){jia_flag=0;set_shi_q++;if(set_shi_q>9)set_shi_q=0;}if(jian_flag==1){jian_flag=0;set_shi_q--;if(set_shi_q<0)set_shi_q=9;}//时十位;=============================P0=table[16];P1=0x20;delay(1);P0=0xff;//时个位;=============================if(shan<20) //数码管闪烁占空比的控制1:1{P0=table[set_shi_q]&0x7f;}elseif(shan>=20){P0=0xff;}P1=0x10;delay(1);P0=0xff;//分十位;=============================P0=table[set_shi_b];P1=0x08;delay(1);P0=0xff;;//分个位;=============================P0=table[set_shi_s];P1=0x04;delay(1);P0=0xff;//秒十位;=============================P0=table[set_shi_g];P1=0x02;delay(1);P0=0xff;//秒个位;=============================P0=table[16];P1=0x01;delay(1);P0=0xff;break;}}}set_shi=set_shi_q*1000+set_shi_b*100+set_shi_s*10+set_shi_g; set_fen=set_fen_s*10+set_fen_g;set_miao=set_miao_s*10+set_miao_g;if(go==0){delay(10);if(go==0)go_flag=1;set_flag=0;}continue;}}void setdisplay(uchar set_aa,uchar set_ab,uchar set_ba,uchar set_bb,uchar set_ca,uchar set_cb) {//时十位;=============================if(shi<=99){P0=table[set_aa];P1=0x20;delay(1);P0=0xff;}else{P0=table[set_aa];if(shan<=20){P1=0x20;}else{P0=0xff;}delay(1);P0=1;}//时个位;=============================P0=table[set_ab];P1=0x10;delay(1);P0=0xff;//分十位;=============================P0=table[set_ba];P1=0x08;delay(1);P0=0xff;//分个位;=============================P0=table[set_bb];P1=0x04;delay(1);P0=0xff;//秒十位;=============================P0=table[set_ca];P1=0x02;delay(1);P0=0xff;//秒个位;=============================if(shi<=99){P0=table[set_cb];P1=0x01;delay(1);P0=0xff;}else{P0=table[set_cb];if(shan<=20){P1=0x01;}else{P0=0xff;}delay(1);P0=0xff;}}//==================================================================== void display(uchar aa,uchar ab,uchar ba,uchar bb,uchar ca,uchar cb){//时十位;=============================P0=table[aa];P1=0x20;delay(1);P0=0xff;//时个位;=============================P0=table[ab]&0x7f;P1=0x10;delay(1);P0=0xff;//分十位;=============================P0=table[ba];P1=0x08;delay(1);P0=0xff;//分个位;=============================P0=table[bb]&0x7f;P1=0x04;delay(1);P0=0xff;//秒十位;=============================P0=table[ca];P1=0x02;delay(1);P0=0xff;//秒个位;=============================P0=table[cb];P1=0x01;delay(1);P0=0xff;}void initiate(){while(go_flag==1) //启动并开始计时{TR0=1;relay1=1;relay3=1;if(shi<=99) //小时数大于99,显示‘三9999三’方式{display(shi_shiwei,shi_gewei,fen_shiwei,fen_gewei,miao_shiwei,miao_gewei);}else{setdisplay(16,shi_qianwei,shi_baiwei,shi_shiwei,shi_gewei,16);}if(shi>=set_shi) //判断时间是否到设置时间{if(fen>=set_fen){if(miao>=set_miao){jingbao=0;while(1) //时间到了则停止计时,数码显示1s闪烁一次{TR0=0;relay1=0;relay3=0;if(jingbao<=20) //警报响二十秒钟,停3分钟。
MAIN.C#include<reg51.h> //通用寄存器头文件#include"clock.h" //对象模块头文件此处包含软件中所有模块的头文件#include"lcd.h"#include"key.h"#include"ad.h"#include"pid.h"#define CYCLE 35121//系统常数定义此处填写系统基本的常数数据例如定时中断时间常数float filter_out,T,t1; /* 此处定义为主模块各函数共用的全局变量unsigned int f; /*unsigned:无符号变量;static:静态变量主函数:void main(){unsigned char /*n,y,r,h,m,s,c,*/b; 此处定义主函数内部使用的全部局部变量//int i=0;clock_init(11,9,28,15,33,40);//定时中断初始化TMOD=TMOD&0xf0; //设定计数器T0为工作方式1,16位计数器方式TMOD=TMOD|0x01;TL0=CYCLE%256; //分别写入时间常数的高8位和低8位TH0=CYCLE/256;EA=1; //打开中断控制逻辑开关ET0=1;TR0=1; //打开计数器逻辑开关//其他模块的初始化clr_screen();convert_da(0);//put_float(2340.789,3,2);// //输出浮点数2340.789,整数后3位,小数前2位main_loop: //监控程序主循环/*n=current_time('n'); /* 此处填写监控程序的散转控制部分y=current_time('y');r=current_time('r');h=current_time('h');m=current_time('m');s=current_time('s');locate(3,7); //显示位置定位style_5x7(2); //输出字库中第2个字符(本程序中为数字2)style_5x7(0);put_int((int)n,2); //输出整型数n(定义的“年”,下为:月日时分秒)style_5x7(12); //输出字库中第12个字符(本程序中为“冒号:”)put_int((int)y,2);style_5x7(12);put_int((int)r,2);style_5x7(12);put_int((int)h,2);style_5x7(15);put_int((int)m,2);style_5x7(15);put_int((int)s,2);*/ //至此,显示完整日期,年月日时分秒locate(2,8);put_float(T,2,1); //输出浮点数T(液晶屏上显示的温度)b=inkey(); //读取键入值,赋给b/*if (b!=0xff){ //如果有键按下locate(5,7+5*i);c=getkey(); //读取键入值,赋给c(注意与inkey的区别)style_5x7(c);i++; //控制字符连续排列输出}*/locate(6,8);if(b!=255){b=getkey();if(b<10){f=(f*10+b)%100; //算出的值赋给f}}t1=(float)f; //f取浮点数赋给t1put_int(t1,2); //输出2位整型数字goto main_loop; //执行主循环}void timer_int()interrupt 1 //定时中断服务程序{unsigned int x; //定义一个辅助变量xunsigned char y; //int:整型(数字)char:字符型static unsigned char count/*,temp_row=0,temp_col=0*/;x=CYCLE+TL0; //重写时间常数TL0=x%256;TH0=x/256;clock_run(); //实时多任务程序此处填写实时多任务类型的多个程序模块key_scan();//convert_da(50);filter_out=Yn(filter_out); //从Yn函数取得DA值T=-0.00009174716*filter_out*filter_out+0.33669798421*filter_out+19.7078734907;//进行标度变换,以便输出温度(一个DA值对应一个温度,上式为确定二次函数)count++;if (count>=31)/*{ //判断大于1秒钟(时间常数30,若是2秒,则61)count=0;locate(temp_row,temp_col);put_float(T,2,1);temp_row++;if (temp_row==8){temp_col=temp_col+25;temp_row=0;}if (temp_col==125){temp_row=0;temp_col=0;}*///下划线部分为了在屏幕上每列输出8个,输出5列的实时温度值,可不做了解{y=pid(t1-T); //将t1-T的值用作PID运算,将PID运算结果赋给ycount=0;convert_da(y); //将y值用作convert_da函数的计算}}CLOCK.H#define SECOND_CONST 30 //定义时间常数30extern void clock_init(unsigned char n,unsigned char y,unsigned char r,unsigned char h,unsigned char m,unsigned char s);extern void clock_run();extern unsigned char current_time(char c);功能: 以上三个函数组成一个标准计时钟对象.其中clock_run为时钟的走时部分,必须放在定时中断中执行.函数clock_init完成时钟初始化,变元h,m,s分别为设定的时、分、秒时间。
大连理工大学实验报告实验时间:2013 年7 月8 日星期一时间:15 :15 ~ 17 :10实验室(房间号):综420 实验台号码: 6 班级:电子1004 姓名:黄佳卿指导教师签字:成绩:实验五 MCS-51单片机与TLC549串行A/D转换器接口芯片编程实验一、实验目的和要求学习掌握TLC549的工作原理及编程方法。
二、实验算法通过TLC549的工作时序来编写程序进行AD转换,采集256次数据进行累加,低位放于R1,高位放于R2,进行平均后即只取高位即可。
三、实验电路图采用DP-51PROC单片机综合仿真实验台,P1口接LED,P3.2、P3.3、P3.4分别接TLC549的DAT、CLK、/CS。
四、实验流程图五、程序清单验证实验程序清单:DAT BIT P3.2CLK BIT P3.3CS BIT P3.4ORG 8000HLJMP 8100HORG 8100HSTART: MOV SP,#60HMOV R3,#00HMOV R1,#00HMOV R2,#00HLOOP: LCALL TLC549_ADC ; CPL A; MOV P1,ALCALL DELAYCLR CADD A,R1MOV R1,ACLR AADDC A,R2MOV R2,ADJNZ R3,LOOPCPL AMOV P1,AMOV R3,#00HMOV R1,#00HMOV R2,#00HSJMP LOOPTLC549_ADC:PUSH 07HCLR ACLR CLKMOV R7,#08HCLR CSNOPLOOP1: SETB CLKMOV C,DATRLC ACLR CLKDJNZ R7,LOOP1SETB CSSETB CLKPOP 07HRETDELAY: PUSH 00HMOV R0,#00HDJNZ R0,$POP 00HRETEND六、实验结果与分析实验运行结果:转动电位器,LED会以二进制的方式变化,当没有加平均滤波的时候最后几位LED会跳动,加了滤波之后LED会很稳定。