找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10889|回复: 8
打印 上一主题 下一主题
收起左侧

基于MS83F0802A单片机的头灯制作原理图和源程序

[复制链接]
跳转到指定楼层
楼主
虽然是个简单的东西但是花了好长时间,写程序期间遇到了好多问题,然后慢慢的修改,直到完成,能够做出来感觉很欣慰,特此上传来共同学习进步。

头灯功能说明书原理图
1.按键按第一下LED1和LED3亮,再按亮LED2,再按全灭。如此循环。
2.关灯状态下,长按2秒以上进入电量指示,电池3.9V以上LED123全部微亮表示满电。
3.电池电压3.6-3.9V,LED2,LED3微亮,电池3.6V以下,LED3微亮。
4.另外,LED2点亮状态下,单片机检测电池电压,电压低于3.2V时,LED2亮5s,关0.5s,重复。



电路原理图如下:


程序截图:


单片机源程序如下:
  1. #include "syscfg.h"
  2. #include "MS83Fxx02.h"
  3. #define _XTAL_FREQ                 4000000 //4T,此定义详解请看MS_Q&A_Sheet.pdf文档
  4. #define LED1 RC2
  5. #define LED2 RC4
  6. #define LED3 RA1
  7. #define KEY  RA6
  8. //#define LED4 RC3//ad转换结果测试
  9. unsigned char keycount=0,LEDCOUNT=0,t=0;
  10. unsigned int flagecount=0,LED1COUNT=0,count=0,count1=0;
  11. unsigned long advalue=0;
  12. bit flage=0,flageled2=0,flageled=0,flage3=0;
  13. float adcvalue=0;
  14. void ENABLE_INTERRUPT(void);
  15. void interrupt ISR(void);
  16. void DEVICE_INIT(void);
  17. void Keycan(void);
  18. void ADC_INIT(void);
  19. void Led1_lighter(void);
  20. void Led2_lighter(void);
  21. void Led3_lighter(void);
  22. void Float_adcvalue(void);
  23. void Keycan(void);
  24. void TIMER1_INIT(void);

  25. /*====================================================
  26. *函数名:main
  27. *功能:主函数
  28. *输入参数:无
  29. *返回参数:无
  30. ====================================================*/
  31. void main(void)
  32. {
  33.         DEVICE_INIT();     //器件初始化
  34.     ADC_INIT();        //adc初始化
  35.     TIMER1_INIT();     //定时器1初始化
  36.     keycount=0;
  37.     LED1=0;
  38.     LED2=0;
  39.     LED3=0;
  40.     ENABLE_INTERRUPT();//进入定时器中断
  41.         while(1)
  42.         { CLRWDT();
  43.       if(!flage) Keycan();
  44.       if(flage||flageled)  Float_adcvalue();
  45.     }
  46. }
  47. /*====================================================
  48. *函数名:interrupt ISR
  49. *功能:中断服务函数
  50. *输入参数:无
  51. *返回参数:无
  52. ====================================================*/
  53. void interrupt ISR(void)
  54. {
  55.         if(T0IE&&T0IF&&!flage3)
  56.         {
  57.                 T0IF = 0;
  58.                 TMR0 = 6;//(256-6)*4=1000us=1ms
  59.        if(flageled2)   LEDCOUNT++;
  60.    
  61.        if(LEDCOUNT==100)
  62.                 {
  63.          LEDCOUNT=0;
  64.             count++;
  65.             if(count==50)
  66.               { count=0;
  67.                 LED2=0;
  68.                 //__delay_ms(500);
  69.                 TMR1ON=1;flage3=1;

  70.               }
  71.          
  72.         }
  73.         

  74.         
  75.         
  76.      }
  77.     if(TMR1IE&&TMR1IF)
  78.         {
  79.                 TMR1IF = 0;
  80.                 TMR1H = 0xFC;
  81.                   TMR1L = 0x17;//重装初值定时时间1ms
  82.           if(flage3){count1++;}
  83.           else LED1COUNT++;
  84.           if(count1==500){LED2=1;count1=0;flage3=0;}
  85.           if(LED1COUNT==3000)  {TMR1ON=0;flage=0;LED1COUNT=0;}
  86.         }
  87. }
  88. /*====================================================
  89. *函数名:DEVICE_INIT
  90. *功能:上电器件初始化
  91. *输入参数:无
  92. *返回参数:无
  93. ====================================================*/
  94. void DEVICE_INIT(void)
  95. {
  96.         OSCCON = 0B01010001; //Bit7   >>> LFMOD=0       >>> WDT振荡器频率=32KHz
  97.                          //Bit6:4 >>> IRCF[2:0]=101 >>> 内部RC频率=4MHz
  98.                          //Bit0   >>> SCS=1         >>> 系统时钟选择为内部振荡器
  99.         MSCKCON = 0B00000000;//Bit6   >>>  VREG_OE=0    >>> 禁止稳压输出
  100.                          //Bit5  >>> T2CKSRC=0  >>> Timer2时钟源为系统时钟
  101.                          //Bit4  >>> SLVREN=0   >>> 关闭LVR
  102.         INTCON = 0B00000000; //暂禁止所有中断
  103.         CMCON0 = 0B00000111; //关闭比较器,CxIN为数字IO口
  104.         ANSEL = 0B10000000;  //所有IO口都为数字IO
  105.         PORTA = 0B00000000;
  106.         TRISA = 0B01000000;  //RA0,RA6为输入,其他为输出
  107.         WPUA = 0B01000000;   //关闭PORTA口的内部上拉除RA6
  108.         PORTC = 0B00000000;
  109.         TRISC = 0B00000000;  //设置所有PORTC口为输出
  110.         WPUC = 0B00000000;   //关闭启PORTC口所有上拉
  111.         OPTION = 0B00000000; //bit7=0,开启PORTA内部上拉总闸
  112.    
  113.    

  114. }



  115. /*====================================================
  116. *函数名:ENABLE_INTERRUPT
  117. *功能:开启所需中断
  118. *输入参数:无
  119. *返回参数:无
  120. ====================================================*/
  121. void ENABLE_INTERRUPT(void)
  122. {
  123.         T0IF = 0;                         //清TIMER0中断标志位
  124.         T0IE = 1;                         //使能TIMER0中断
  125.     TMR1IF = 0;                       //清TIMER1中断标志位
  126.         TMR1IE = 1;                       //使能TIMER1中断               
  127.     PEIE = 1;                         //开启外设总闸 timer1属于外设
  128.          GIE = 1;                         //开启总中断
  129. }
  130. /*====================================================
  131. *函数名:TIMER1_INIT
  132. *功能:Tiemr1初始化
  133. *输入参数:无
  134. *返回参数:无
  135. ====================================================*/
  136. void TIMER1_INIT(void)
  137. {
  138.         TMR1H = 0xFC;
  139.     TMR1L = 0x17;                  //Timer1初值为0xFC17=64535
  140.         T1CON = 0B00000000;            //预分频值5,4位 11=1:8
  141.                                    //             10=1:4
  142.                                    //             01=1:2
  143.                                    //             00=1:1
  144.                                  
  145. }

  146. /*====================================================
  147. *函数名:Keycan
  148. *功能:按键函数
  149. *输入参数:无
  150. *返回参数:无
  151. ====================================================*/

  152. void Keycan(void)
  153. {if(KEY==0)
  154. __delay_ms(20);
  155. if(KEY==0)
  156. {


  157. while(!KEY)
  158.    {__delay_ms(10);
  159.    flagecount++;
  160.    if((LED1==0)&&(LED2==0)&&(LED3==0)&&(flageled==0)&&(flagecount>299))//这里加flageled=0是为了处在LED2亮灯状态时长按出现电量提示
  161.       break;
  162.    }
  163.    
  164. if(flagecount>299)

  165.    {if((LED1==0)&&(LED2==0)&&(LED3==0)&&(flageled==0))//这里加flageled=0是为了处在LED2亮灯状态时长按出现电量提示
  166.       {flage=1;
  167.        flagecount=0;
  168.       }
  169.    else goto begin;
  170.    }

  171. else
  172. {
  173.   {if(flage==0)
  174.      {  begin:keycount++;
  175.         flagecount=0;flage=0;
  176.        switch(keycount)
  177.              {case 1:LED1=1;LED2=0;LED3=1;flageled=0;flageled2=0;break;
  178.               case 2:LED1=0;LED2=1;LED3=0;flageled=1;flageled2=0;break;
  179.               case 3:LED1=0;LED2=0;LED3=0;keycount=0;flageled=0;flageled2=0;break;
  180.              default: break;
  181.              }
  182.      }   
  183.   }
  184. }
  185. }
  186. }

  187. /*====================================================
  188. *函数名:ADC_INIT
  189. *功能:比较器初始化
  190. *输入参数:无
  191. *返回参数:无
  192. ====================================================*/
  193. void ADC_INIT(void)
  194. {
  195.         ANSEL = 0B10000000;    //设置RA0为模拟输入口
  196.         ADCON1 = 0B01100000;   //DIVS=0,时钟选FOSC
  197.                                //ADCS[2:0]=110,分频FOSC/64
  198.         ADCON0 = 0B10111100;       //B7,ADFM=1,结果右对齐
  199.                                //B6:5,VCFG=00,参考电压VDD
  200.                                //B6:5,VCFG=01,参考电压内部2V
  201.                                //B6:5,VCFG=10,参考电压内部3V
  202.                                //B6:5,VCFG=11,参考电压Vref
  203.                                //B4:2,CHS=000,选择AN7通道
  204.                                //B1,GO,AD转换状态位
  205.                                //B0,ADON=1,ADC使能

  206. }
  207. /*====================================================
  208. *函数名:GET_ADC_VALUE
  209. *功能:开启AD转换,参考电压为VDD
  210. *输入参数:ADC通道数
  211. *返回参数:采样到的AD值
  212. ====================================================*/
  213. unsigned int GET_ADC_VALUE()
  214. {
  215.         unsigned int TempADCBuffer=0;

  216.         ADCON0 |= 0b10000001;     //开启ADC电路
  217.         __delay_us(10);           //等待采集到电压
  218.         GO_DONE = 1;              //开启转换
  219.         while(GO_DONE==1) CLRWDT();//等待转换完成
  220.         TempADCBuffer = ADRESH;
  221.         TempADCBuffer = (TempADCBuffer<<8)|ADRESL;
  222.         ADON = 0;
  223.         return(TempADCBuffer);

  224. }
  225. /*====================================================
  226. *函数名:u16_adcvalue
  227. *功能:开启AD转换,参考电压为VDD
  228. *输入参数:ADC通道数
  229. *返回参数:采样到的AD值
  230. ====================================================*/
  231. void Float_adcvalue(void)
  232. { unsigned char i;
  233.   for(i=0;i<20;i++)
  234.   { advalue+=GET_ADC_VALUE();}
  235.   advalue=advalue/20;
  236.   adcvalue=advalue;
  237.   adcvalue=adcvalue/1023*2.0000;
  238.    //if(adcvalue>2) Led1_lighter();
  239.    if(flageled)
  240.    {if(adcvalue<0.80) flageled2=1;
  241.    else {flageled2=0;LED1=0;LED2=1;LED3=0;}
  242.    }
  243.    
  244.    
  245.    else
  246.    { flageled=0;flageled2=0;
  247.      if(adcvalue>=1.07)
  248.        { Led1_lighter();}
  249.      if(adcvalue<1.07,adcvalue>=0.98)
  250.        { Led2_lighter();}
  251.      if(adcvalue<0.98)
  252.        {Led3_lighter();}
  253.       TMR1ON=1;
  254.       
  255.    }


  256. }
  257. /*====================================================
  258. *函数名:Led1_lighter()
  259. *功能:微亮3个灯
  260. *输入参数:
  261. *返回参数:
  262. ====================================================*/
  263. void Led1_lighter(void)//微亮3个灯
  264. {LED1=1;LED2=1;LED3=1;
  265. __delay_us(500);
  266. LED1=0;LED2=0;LED3=0;
  267. //__delay_us(1);
  268. }

  269. /*====================================================
  270. *函数名:Led2_lighter()
  271. *功能:微亮2个灯
  272. *输入参数:
  273. *返回参数:
  274. ====================================================*/
  275. void Led2_lighter(void)//微亮2个灯
  276. {LED1=0;LED2=1;LED3=1;
  277. __delay_us(500);
  278. ……………………

  279. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码




全部资料51hei下载地址:
头灯制作.zip (201.87 KB, 下载次数: 89)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:1 发表于 2018-8-24 16:31 | 只看该作者
程序是反汇编得到的吗?
回复

使用道具 举报

板凳
ID:1 发表于 2018-8-24 16:33 | 只看该作者
看到了 有c语言的版本,好资料,51黑有你更精彩!!!
回复

使用道具 举报

地板
ID:391730 发表于 2018-8-30 19:31 | 只看该作者
adcvalue=adcvalue/1023*2.0000  明明参考电压取得是VDD,为何乘的是2?
回复

使用道具 举报

5#
ID:76293 发表于 2018-8-30 21:33 | 只看该作者
liuguonianhua 发表于 2018-8-30 19:31
adcvalue=adcvalue/1023*2.0000  明明参考电压取得是VDD,为何乘的是2?

内部2v
回复

使用道具 举报

6#
ID:395609 发表于 2018-9-9 13:59 | 只看该作者
你好,请问下有没有MS83F0802相关的资料或者数据手册?请不吝赐教。网上没找到相关的资料  谢谢
回复

使用道具 举报

7#
ID:436758 发表于 2018-11-30 20:00 | 只看该作者
看样子用这芯片的人好少, 用这东东做下遥控接收还是很好的 便宜实惠
回复

使用道具 举报

8#
ID:391730 发表于 2019-2-14 20:06 | 只看该作者
楼主完全没有实现上述功能,程序全是错的!DEVICE_INIT(void)这个初始化引脚函数中,将PA6配置成了输入TRISA = 0B01000000; ,实际这个输入指的是模拟信号输入,如果接的是开关信号应该将应该将PA6配置为输出才对!输入在这款单片机中是为了ADC采集模拟信号!这是第一处错误,第二处错误,楼主将ADC_INIT()中,将采集通道设置成了1/4 VDD,而在Float_adcvalue(void)中用的是adcvalue=adcvalue/1023*2.0000;这个值根本就不是VDD的值,而是1/4 vdd的值!本来想参考楼主代码的,但是看到这么多漫不经心的错误,完全是误人子弟!
回复

使用道具 举报

9#
ID:76293 发表于 2019-3-1 14:39 | 只看该作者
liuguonianhua 发表于 2019-2-14 20:06
楼主完全没有实现上述功能,程序全是错的!DEVICE_INIT(void)这个初始化引脚函数中,将PA6配置成了输入TRIS ...

你厉害
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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