作为一个初学者,如何学好单片机,课堂上的内容过于粗浅
单片机源程序如下:
- /*---------------------------------------------------------------
- 项目名称:自动售水机系统
- ----------------------------------------------------------------*/
- #include"reg52.h"
- #include"pcf8591.h"
- #include"iic.h" //iic协议
- #include"ct107.h" //CT107单片机初始化
- #include"deplay.h" //延时
- #define AddWr 0x90 //写数据地址
- #define AddRd 0x91 //读数据地址
- sbit key6=P3^1; //定义按键端口
- sbit key7=P3^0;
- unsigned char code smg_du[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数码管段选“0~9”
- unsigned char code smg_we[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //数码管位选
- unsigned char tab[8]={0,0,5,0,0,0,0,0}; //显示数组
- unsigned int water,total; //定义水量,总价
- float price; //定义单价
- unsigned char light; //定义光照强度变量
- bit flag,flag1,flag2; //定义标志位
- unsigned char ReadADC(unsigned char Ch1); //读AD函数,Ch1为通道号,取值0~3;
- void diswork(); //数据处理函数
- main()
- {
- price=0.5; //设定单价为0.5元/L
- TMOD=0x11; //设置定时器0,1为16位定时器
- TH0=(65536-50000)/256; //设定定时器0初值50ms,用于累计水量
- TL0=(65536-50000)%256;
- TH1=(65536-2000)/256; //设定定时器0初值2ms,用于扫描数码管和L1
- TL1=(65536-2000)%256;
- TR1=1; //开定时器1
- TR0=1; //开定时器0
- ET1=1; //开定时器1中断允许位
- EA=1; //开总中断
- ct107_init();
- while(1) //停止
- {
- if(!key6) //判断按键是否按下
- {
- deplay_50us(200); //消抖
- if(!key6) //确认按键按下
- {
- ET0=0;
- P2&=0x1f;
- RELAY=0; //关继电器
- BUZZ=0; //避免蜂鸣器的影响
- P2|=Y5C;
- P2&=0x1f;
- flag=1; //停止标志位
- flag2=0; //按下停止后把许可启动标志位置0,方可进入下次启动
- }
- }
- if(!flag2) //许可启动标志位为0才可启动
- if(!key7) //启动
- {
- deplay_50us(200);
- if(!key7)
- {
- ET0=1;
- water=0; //水量清0
- total=0; //总价清0
- P2&=0x1f;
- RELAY=1; //开继电器
- BUZZ=0;
- P2|=Y5C;
- P2&=0x1f;
- flag=0; //复位停止标志位
- flag2=1; //置位许可启动标志位防止再次进入启动程序
- }
- }
- diswork(); //显示数据处理
- light=ReadADC(1); //读AD数据(光敏电阻)
- if(light<64) //判断电压是否下于1.25V。1.25*255/5=64
- flag1=1;
- else
- flag1=0;
- }
- }
- void diswork()
- {
- if(flag) //停止时显示总价,启动时显示水量
- {
- total=(unsigned int)(water*price);
- tab[4]=total/1000;
- tab[5]=total%1000/100;
- tab[6]=total%100/10;
- tab[7]=total%10;
- }
- else
- {
- tab[4]=water/1000;
- tab[5]=water%1000/100;
- tab[6]=water%100/10;
- tab[7]=water%10;
- }
- }
- unsigned char ReadADC(unsigned char Ch1) //读通道Ch1的数据
- {
- unsigned char Data;
- init_iic();
- Start();
- Send(AddWr);
- Ack();
- Send(0x40|Ch1);
- Ack();
- Start();
- Send(AddRd);
- Ack();
- Data=Read();
- Scl=0;
- NoAck();
- Stop();
- return Data;
- }
- void timeint_0() interrupt 1 //定时器0中断用于计算水量,其中断优先级比定时器1中断高,防止了中断被打断,使数据更准确
- {
- static unsigned char k;
- TH0=(65536-50000)/256; //每50ms进一次中断
- TL0=(65536-50000)%256;
- if(k) //每100ms水量增加10mL
- {
- k=0;
- if(water==9999)
- {
- ET0=0;
- P2&=0x1f;
- RELAY=0;
- BUZZ=0;
- P2|=Y5C;
- P2&=0x1f;
- flag=1;
- flag2=0;
- }
- else
- water++;
- }
- else
- k++;
- }
- void timeint_1() interrupt 3
- { //数码管和L1扫描函数
- unsigned char com[8]={0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; //用于控制数码管的亮灭
- static char i;
- TH1=(65536-2500)/256; //每2ms扫描一次
- TL1=(65536-2500)%256;
- P2&=0x1f;
- P0=0xff;
- P2|=Y7C;
- P2&=0x1f;
- P0=smg_we[i]&com[i];
- P2|=Y6C;
- P2&=0x1f;
- if(i==1|i==5)
- P0=smg_du[tab[i]]&0x7f; //为第二和第六个数码管加小数点
- else
- P0=smg_du[tab[i]];
- P2|=Y7C;
- P2&=0x1f;
- if(flag1) //开L1
- {
- P2&=0x1f;
- P0=0xfe;
- P2=Y4C;
- P2&=0x1f;
- }
- else //关L1
- {
- P2&=0x1f;
- P0=0xff;
- P2=Y4C;
- P2&=0x1f;
- }
- if(i==7) //扫描完8个数码管就清零从新扫描
- {
- i=0;
- }
- else
- i++;
- }
复制代码
所有资料51hei提供下载:
自动售水机.zip
(517.53 KB, 下载次数: 4)
|