找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3177|回复: 4
收起左侧

看不懂这个单片机程序的中断和计数初值

[复制链接]
ID:262 发表于 2016-3-11 22:20 | 显示全部楼层 |阅读模式
本帖最后由 heicad 于 2016-3-11 22:22 编辑

下面是一个51单片机的程序:中断和计数初值这看不懂
  1. #include<reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. uint num=0;                           //外部中断次数
  5. uchar num1=0;
  6. uint Speed_dat=0;
  7. uint Total_Dis=0;
  8. uchar Beep_speed=40;
  9. sbit KEY1=P3^5;
  10. sbit KEY2=P3^6;
  11. sbit KEY3=P3^7;

  12. void delayms(uint xms)
  13. {
  14.         uint i,j;
  15.         for(i=xms;i>0;i--)
  16.                 for(j=110;j>0;j--);
  17. }
  18. #include"LCD1602.H"
  19. #include"AT24C02.H"
  20. void keyscan()
  21. {
  22.         if(!KEY1)
  23.         {
  24.                 delayms(5);
  25.                 if(!KEY1)
  26.                 {
  27.                         if(Beep_speed<255)
  28.                         Beep_speed++;
  29.                         while(!KEY1);
  30.                 }
  31.         }        

  32.         else if(!KEY2)
  33.         {
  34.                 delayms(5);
  35.                 if(!KEY2)
  36.                 {
  37.                         if(Beep_speed>0)
  38.                         Beep_speed--;
  39.                         while(!KEY2);
  40.                 }
  41.         }        

  42.         else if(!KEY3)
  43.         {
  44.                 delayms(5);
  45.                 if(!KEY3)
  46.                 {
  47.                         Write_AT24C02_Byte(0,0);
  48.                         Write_AT24C02_Byte(1,0);
  49.                         Total_Dis=0;
  50.                         dis_Mileage();
  51.                         while(!KEY3);
  52.                 }
  53.         }        
  54. }

  55. void main()
  56. {
  57.         uchar dat=0;
  58.         float M_dat=0.0;
  59.         init_1602();
  60.         Init_AT24C02();
  61.         dat=Read_AT24C02_Random(0);
  62.         Total_Dis=dat*256+Read_AT24C02_Random(1);
  63.         dis_Mileage();
  64.         TMOD=0X01;
  65.         TH0=(65536-1000)/256;
  66.         TL0=(65536-1000)%256;
  67.         ET0=1;
  68.         TR0=1;
  69.         IT0=1;         //边沿触发中断
  70.         EX0=1;
  71.         EA=1;
  72.         while(1)
  73.         {
  74.                 if(num1>99)
  75.                 {
  76.                         num1=0;
  77.                         M_dat+=(float)(Cur_Speed/3.60);                        //每0.1s走的米数
  78.                 }
  79.                 if(M_dat>1000.0)          //路程每增加100m储存一次
  80.                 {
  81.                         M_dat-=1000.0;
  82.                         Total_Dis+=1;
  83.                         Write_AT24C02_Byte(0,Total_Dis/256);
  84.                         Write_AT24C02_Byte(1,Total_Dis%256);
  85.                         dis_Mileage();        
  86.                 }
  87.                 display();
  88.                 keyscan();        
  89.         }
  90. }

  91. void T0_time() interrupt 1                 //定时器0
  92. {
  93.         TH0=(65536-1000)/256;
  94.         TL0=(65536-1000)%256;
  95.         if(num<500)
  96.         num++;
  97.         else
  98.         Speed_dat=0;
  99.         if(num1<100)
  100.         num1++;               
  101. }

  102. void ex_0() interrupt 0           //外部中断0
  103. {
  104.         Speed_dat=(500/num);
  105.     num=0;
  106. }
  107. #define uchar unsigned char
  108. #define uint unsigned int           
  109. sbit EN=P2^7;
  110. sbit RS=P2^5;
  111. sbit RW=P2^6;
  112. sbit BEEP=P2^0;
  113. sbit LED1=P1^2;
  114. sbit LED2=P1^3;
  115. uchar LCD1602_Table[]="0123456789";
  116. //LCD1602显示标尺     //0123456789abcdef
  117. uchar code DIS_TAB1[]={" Speed:---Km/h  "};         
  118. uchar code DIS_TAB2[]={"M:     Km---Km/h"};           
  119. uint sum_dat=0;
  120. uchar Cur_Speed=0;
  121. extern uint Speed_dat;
  122. extern uint Total_Dis;
  123. extern void delayms(uint xms);
  124. void WRITE_LCD1602_DAT(uchar date)
  125. {
  126.         EN=0;
  127.         RS=1;
  128.         P0=date;
  129.         EN=0;
  130.         delayms(5);
  131.         EN=1;
  132. }
  133. void WRITE_LCD1602_COM(uchar date)
  134. {
  135.         EN=0;
  136.         RS=0;
  137.         P0=date;
  138.         EN=0;
  139.         delayms(5);
  140.         EN=1;
  141. }
  142. void init_1602()
  143. {
  144.          unsigned char i;
  145.         RW=0;
  146.         WRITE_LCD1602_COM(0x38);
  147.         WRITE_LCD1602_COM(0x0c);
  148.         WRITE_LCD1602_COM(0x06);
  149.         WRITE_LCD1602_COM(0x01);
  150.         WRITE_LCD1602_COM(0x80);
  151.         for(i=0;i<16;i++)
  152.         WRITE_LCD1602_DAT(DIS_TAB1[i]);
  153.         WRITE_LCD1602_COM(0x80+0x40);
  154.         for(i=0;i<16;i++)
  155.         WRITE_LCD1602_DAT(DIS_TAB2[i]);
  156. }

  157. void display()
  158. {        
  159.         static uint dat=0;
  160.         static uchar i=0;
  161.         if(i<6)
  162.         {
  163.                 i++;
  164.                 sum_dat+=Speed_dat;        
  165.         }
  166.         else
  167.         {
  168.                 i=0;
  169.                 dat=sum_dat/10;
  170.                 sum_dat=0;
  171.         }
  172.         Cur_Speed=dat;
  173.         WRITE_LCD1602_COM(0x80+7);
  174.         if(dat/100>0)        
  175.         WRITE_LCD1602_DAT(LCD1602_Table[dat%1000/100]);
  176.         else
  177.         WRITE_LCD1602_DAT(' ');
  178.         if(dat/10>0)        
  179.         WRITE_LCD1602_DAT(LCD1602_Table[dat%100/10]);
  180.         else
  181.         WRITE_LCD1602_DAT(' ');
  182.         WRITE_LCD1602_DAT(LCD1602_Table[dat%10]);

  183.         WRITE_LCD1602_COM(0x80+9+0x40);
  184.         if(Beep_speed/100>0)        
  185.         WRITE_LCD1602_DAT(LCD1602_Table[Beep_speed%1000/100]);
  186.         else
  187.         WRITE_LCD1602_DAT(' ');
  188.         if(Beep_speed/10>0)        
  189.         WRITE_LCD1602_DAT(LCD1602_Table[Beep_speed%100/10]);
  190.         else
  191.         WRITE_LCD1602_DAT(' ');
  192.         WRITE_LCD1602_DAT(LCD1602_Table[Beep_speed%10]);

  193.         if(dat>Beep_speed)
  194.         {
  195.                 if(i<3)
  196.                 BEEP=0;
  197.                 else
  198.                 BEEP=1;
  199.                 LED1=0;
  200.                 LED2=1;
  201.         }
  202.         else
  203.         {
  204.                 BEEP=1;        
  205.                 LED1=1;
  206.                 LED2=0;
  207.         }
  208.         
  209. }

  210. void dis_Mileage()
  211. {
  212.         WRITE_LCD1602_COM(0x80+0x40+2);
  213.         if(Total_Dis/1000>0)
  214.         WRITE_LCD1602_DAT(LCD1602_Table[Total_Dis%10000/1000]);
  215.         else
  216.         WRITE_LCD1602_DAT(' ');
  217.         if(Total_Dis/100>0)
  218.         WRITE_LCD1602_DAT(LCD1602_Table[Total_Dis%1000/100]);
  219.         else
  220.         WRITE_LCD1602_DAT(' ');
  221.         WRITE_LCD1602_DAT(LCD1602_Table[Total_Dis%100/10]);
  222.         WRITE_LCD1602_DAT('.');
  223.         WRITE_LCD1602_DAT(LCD1602_Table[Total_Dis%10]);
  224. }


  225. #include<intrins.h>
  226. #define        AT24C02_OP_READ        0xa1                // AT24C02器件地址以及读取操作
  227. #define        AT24C02_OP_WRITE 0xa0                // AT24C02器件地址以及写入操作
  228. //#define        AT24C02_MAX_ADDR 0xff                // AT24C02最大地址
  229. //unsigned char code dis_code[]={0x7e,0xbd,0xdb,0x7e,0xdb,0xbd,0x7e,0xff};// 写入到AT24C02的数据串
  230. sbit AT24C02_SDA=P1^1;
  231. sbit AT24C02_SCL=P1^0;
  232. //sbit AT24C02_WP=P3^3;           //写保护  “=0”读写  “=1” 只读
  233. /*****************延时子程序***********************/
  234. void Delay_1ms(unsigned int xms)
  235. {
  236.            unsigned int i,j;
  237.            for(i=xms;i>0;i--)
  238.                    for(j=122;j>0;j--);
  239. }
  240. /*****************24C02初始化子程序***********************/
  241. void Init_AT24C02()
  242. {
  243.          AT24C02_SDA=1;   //总线空闲时,因各设备都是集电极或漏极开路,上拉电阻使SDA和SCL线都保持高电平。
  244. //        AT24C02_WP=1;
  245.          AT24C02_SCL=1;
  246.          _nop_();
  247.          _nop_();
  248.          _nop_();
  249.          _nop_();
  250. }
  251. /*****************24C02起始信号子程序***********************/
  252. void AT24C02_Start()

  253. {
  254.         AT24C02_SDA=1;
  255.         _nop_();
  256.         _nop_();
  257.         AT24C02_SCL=1;
  258.         _nop_();
  259.         _nop_();
  260.         AT24C02_SDA=0;
  261.         _nop_();
  262.         _nop_();
  263.         _nop_();
  264.         _nop_();
  265.         AT24C02_SCL=0;
  266. }
  267. /*****************24C02停止信号子程序***********************/
  268. void AT24C02_Stop()
  269. {
  270.         AT24C02_SDA=0;
  271.         _nop_();
  272.         _nop_();
  273.         AT24C02_SCL=1;
  274.         _nop_();
  275.         _nop_();
  276.         _nop_();
  277.         _nop_();
  278.         AT24C02_SDA=1;
  279.         _nop_();
  280.         _nop_();
  281. }
  282. /*****************24C02应答子程序***********************/
  283. void AT24C02_ACK()
  284. {
  285.         AT24C02_SDA=1;                        // 读取应答
  286.         _nop_();
  287.         _nop_();
  288.         AT24C02_SCL=1;
  289.         _nop_();
  290.         _nop_();
  291.         _nop_();
  292.         _nop_();
  293.         while(AT24C02_SDA);                //等待应答信号
  294.         AT24C02_SCL=0;
  295.         _nop_();
  296.         _nop_();
  297. }
  298. /*****************读出24C02数据子程序***********************/
  299. unsigned char Read_AT24C02_DATA()
  300. {
  301.         unsigned char i,read_data;
  302.         for(i=0;i<8;i++)
  303.         {
  304.                 AT24C02_SCL=1;
  305.                 _nop_();_nop_();_nop_();_nop_();               
  306.                 read_data<<=1;                                                           //从高位到底位
  307.                 read_data|=(unsigned char)AT24C02_SDA;
  308.                 AT24C02_SCL=0;
  309.                 _nop_();_nop_();_nop_();_nop_();
  310.         }
  311.         return(read_data);
  312. }
  313. /*****************写入24C02数据子程序***********************/
  314. void Write_AT24C02_DATA(unsigned char write_data)
  315. {
  316.         unsigned char i;
  317.         for(i=0;i<8;i++)                // 循环移入8个位
  318.         {
  319.                 AT24C02_SDA=(bit)(write_data&0x80);
  320.                 _nop_();
  321.                 AT24C02_SCL=1;
  322.                 _nop_();
  323.                 _nop_();
  324.                 AT24C02_SCL=0;
  325.                 write_data<<=1;
  326.         }
  327. }

  328. /*****************字节写入24C02数据子程序***********************/
  329. void Write_AT24C02_Byte(unsigned char addr, unsigned char write_data) // 在指定地址addr处写入数据write_data
  330. {
  331.         AT24C02_Start();                                                //发起始命令
  332.         Write_AT24C02_DATA(AT24C02_OP_WRITE);        //从机地址写命令
  333.         AT24C02_ACK();
  334.         Write_AT24C02_DATA(addr);                                 //发送AT24C02的字节地址
  335.         AT24C02_ACK();
  336.         Write_AT24C02_DATA(write_data);                          //发送数据到被寻址的存储单元
  337.         AT24C02_ACK();
  338.         AT24C02_Stop();                                                        //停止信号
  339.         Delay_1ms(10);                                                        //延时等待AT24C02内部数据的擦写
  340. }

  341. unsigned char Read_AT24C02_Current()
  342. // 在当前地址读取
  343. {
  344.         unsigned char read_data;
  345.         AT24C02_Start();
  346.         Write_AT24C02_DATA(AT24C02_OP_READ);
  347.         AT24C02_ACK();
  348.         read_data = Read_AT24C02_DATA();
  349.         AT24C02_Stop();
  350.         return read_data;
  351. }

  352. unsigned char Read_AT24C02_Random(unsigned char addr)
  353. // 在指定地址读取
  354. {
  355.         AT24C02_Start();
  356.         Write_AT24C02_DATA(AT24C02_OP_WRITE);
  357.         AT24C02_ACK();
  358.         Write_AT24C02_DATA(addr);
  359.         AT24C02_ACK();
  360.         return(Read_AT24C02_Current());
  361. }
复制代码


回复

使用道具 举报

ID:185870 发表于 2017-4-3 21:27 | 显示全部楼层
同学,你好啊,你看懂了没,求解释。跟你一样的问题
回复

使用道具 举报

ID:262 发表于 2016-3-11 22:21 | 显示全部楼层
heicad 发表于 2016-3-11 22:20
如果这个看不懂,你需要再继续从基础学起。

简单地说如果不给定时器设定初值,他就从0开始计数,如果给 ...

那这个是测速,然后显示出速度与里程,但我看不出它的半径什么的设在哪里,能帮解释一下吗,中断那个我问了同学,了解了不少。
回复

使用道具 举报

ID:262 发表于 2016-3-11 22:21 | 显示全部楼层
简单地说如果不给定时器设定初值,他就从0开始计数,如果给他一个初值,就从初值基础上计数,定时器计数满后,会产生中断。定时/计数器计数到0FFFFH(16进制)也就是65536计满,(65536-1000)意思是从64536开始计数,再加1000个机器周期,计数器满,产生中断。至于(65536-1000)/256,就是将256的倍数装进定时器的高位寄存器,(65536-1000)%256,就是将256的余数装进定时器的低位寄存器,因为51单片机是8位的,所以低位只能计数到255,再加1便产生进位。进到高8位中。如果你手工计算好以后,将倍数和余数分别赋值给TH、TL也是一样。
回复

使用道具 举报

ID:262 发表于 2016-3-11 22:20 | 显示全部楼层
如果这个看不懂,你需要再继续从基础学起。

简单地说如果不给定时器设定初值,他就从0开始计数,如果给他一个初值,就从初值基础上计数,定时器计数满后,会产生中断。定时/计数器计数到0FFFFH(16进制)也就是65536计满,(65536-1000)意思是从64536开始计数,再加1000个机器周期,计数器满,产生中断。至于(65536-1000)/256,就是将256的倍数装进定时器的高位寄存器,(65536-1000)%256,就是将256的余数装进定时器的低位寄存器,因为51单片机是8位的,所以低位只能计数到255,再加1便产生进位。进到高8位中。如果你手工计算好以后,将倍数和余数分别赋值给TH、TL也是一样。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表