找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4995|回复: 10
收起左侧

电动牙刷的MCU驱动程序

  [复制链接]
ID:297748 发表于 2019-6-17 13:32 | 显示全部楼层 |阅读模式
这是电动牙刷的驱动程序,电路可以采用电池供电,也可以USB供电,可以检测电量的多少

单片机源程序如下:
  1. #include "main.h"

  2. void main(void)
  3. {
  4.         SystemInit();
  5.         while(1)
  6.         {
  7.                 BatteryVoltageWarning();
  8.                 KeyScan();
  9.                 switch (key_flag)
  10.                 {
  11.                         case 0: Led50 = 1;Led70 = 1;Led100 = 1;  //档位指示灯全灭
  12.                                         MotorA = 1;MotorB = 1;   //电机不转
  13.                                         break;
  14.                         case 1: Led50 = 0;Led70 = 1;Led100 = 1;  //1挡指示灯亮
  15.                                         MotorA = 0;MotorB = 1;
  16.                                         break;
  17.                         case 2: Led50 = 1;Led70 = 0;Led100 = 1;  //2挡指示灯亮
  18.                                        
  19.                                         break;
  20.                         case 3: Led50 = 1;Led70 = 1;Led100 = 0;  //3挡指示灯亮
  21.                                        
  22.                                         break;
  23.                         default: break;
  24.                 }
  25.                 if(time_flag == 4)   //time_flag为4时,即4*30s=120s,2分钟,此时电机停转
  26.                         key_flag = 0;                       
  27.         }
  28. }

  29. /******延时x毫秒******/
  30. void DelayMs( uint x )                //@11.0592MHz
  31. {
  32.         uint a;
  33.         for(a=0;a<x;a++)
  34.         {
  35.                 uchar i, j;
  36.                 _nop_();
  37.                 i = 2;
  38.                 j = 199;
  39.                 do
  40.                 {
  41.                         while (--j);
  42.                 } while (--i);
  43.         }
  44. }

  45. /*******系统初始化******/
  46. void SystemInit()
  47. {
  48.         Led50 = 1;
  49.         Led70 = 1;
  50.         Led100 = 1;
  51.         LedPower = 1;
  52.         ModeKey = 1;
  53.         MotorA = 1;
  54.         MotorB = 1;
  55.         Timer0Init();
  56. }

  57. /*******定时器0初始化*****/
  58. void Timer0Init()                //333us @11.0592MHz  0.03%误差
  59. {
  60.         TMOD &= 0xF0;                //设置定时器模式
  61.         TMOD |= 0x01;                //设置定时器模式
  62.         TL0 = 0xCD;                //设置定时初值
  63.         TH0 = 0xFE;                //设置定时初值
  64.         TF0 = 0;                //清除TF0标志
  65.         TR0 = 1;                //定时器0开始计时
  66.         ET0 = 1;          //开启定时器0中断
  67.         EA = 1;     //开启总中断
  68. }

  69. /*******读ADC0832函数******/
  70. uchar Adc0832(uchar channel)     //AD转换,返回结果
  71. {
  72.     uchar i=0;
  73.     uchar j;
  74.     uint dat=0;
  75.     uchar ndat=0;

  76.     if(channel==0)channel=2;
  77.     if(channel==1)channel=3;
  78.     ADDI=1;
  79.     _nop_();
  80.     _nop_();
  81.     ADCS=0;                    //拉低CS端
  82.     _nop_();
  83.     _nop_();
  84.     ADCLK=1;                   //拉高CLK端
  85.     _nop_();
  86.     _nop_();
  87.     ADCLK=0;                   //拉低CLK端,形成下降沿1
  88.     _nop_();
  89.     _nop_();
  90.     ADCLK=1;                   //拉高CLK端
  91.     ADDI=channel&0x1;
  92.     _nop_();
  93.     _nop_();
  94.     ADCLK=0;                   //拉低CLK端,形成下降沿2
  95.     _nop_();
  96.     _nop_();
  97.     ADCLK=1;                   //拉高CLK端
  98.     ADDI=(channel>>1)&0x1;
  99.     _nop_();
  100.     _nop_();
  101.     ADCLK=0;                   //拉低CLK端,形成下降沿3
  102.     ADDI=1;                    //控制命令结束
  103.     _nop_();
  104.     _nop_();
  105.     dat=0;
  106.     for(i=0;i<8;i++)
  107.     {
  108.         dat|=ADDO;            //收数据
  109.         ADCLK=1;
  110.         _nop_();
  111.         _nop_();
  112.         ADCLK=0;              //形成一次时钟脉冲
  113.         _nop_();
  114.         _nop_();
  115.         dat<<=1;
  116.         if(i==7)dat|=ADDO;
  117.     }  
  118.     for(i=0;i<8;i++)
  119.     {
  120.         j=0;
  121.         j=j|ADDO;            //收数据
  122.         ADCLK=1;
  123.         _nop_();
  124.         _nop_();
  125.         ADCLK=0;             //形成一次时钟脉冲
  126.         _nop_();
  127.         _nop_();
  128.         j=j<<7;
  129.         ndat=ndat|j;
  130.         if(i<7)ndat>>=1;
  131.     }
  132.     ADCS=1;                 //拉低CS端
  133.     ADCLK=0;                //拉低CLK端
  134.     ADDO=1;                 //拉高数据端,回到初始状态
  135.     dat<<=8;
  136.     dat|=ndat;
  137.     return(dat);            //return ad k         
  138. }

  139. /*******电池低电量警告******/
  140. void BatteryVoltageWarning()
  141. {
  142.         ad_data =Adc0832(0);         //读取电池电压采样值
  143.         //ADC0832模数转换是8位ADC芯片,转换回来的数值是0-255,0V时是0,5V时是255,相应的倍数就是255/5=51
  144.         //因此,将转换回来的数除以51,就得到相应的电压值了
  145.         battery_voltage = (double)(ad_data)/51.0;      
  146.         if(battery_voltage < 0.7)     //当电池电压小于0.7V,即电量低于20%时,低电量指示灯亮
  147.                 LedPower = 0;
  148.         else
  149.                 LedPower = 1;
  150. }

  151. /*******按键扫描******/
  152. uchar KeyScan()
  153. {
  154.         if(!ModeKey)
  155.         {
  156.                 DelayMs(10);
  157.                 if(!ModeKey)
  158.                 {
  159.                         time_30s = 0;
  160.                         time_flag = 0;   //每次按档位模式按键,电机转动都要复位,即清零已经转动的时间
  161.                         key_flag++;
  162.                         if(key_flag > 3)
  163.                                 key_flag = 0;
  164.                 }
  165.                 while(!ModeKey);
  166.         }
  167.         return key_flag;       
  168. }

  169. /*******产生电机PWM******/
  170. void MotorControl(uchar pwm, uchar ab)
  171. {
  172.         if(pwm > 10)
  173.                 pwm = 10;
  174.         if(time_30s > 90000)  //约为90000*333us=30s
  175.         {
  176.                 time_30s = 0;
  177.                 time_flag++;    //每30s停转一次,每停转一次time_flag就加一
  178.                 if(time_flag > 4)   //time_flag加到4,即4*30s=120s,2分钟
  179.                         time_flag = 0;
  180.                 MotorA = 1;
  181.                 MotorB = 1;      
  182.                 DelayMs(1000);  //电机每隔30s停转1s
  183.         }
  184.         else
  185.         {
  186.                 if(time_pwm > 10)  //PWM周期为10*333us=3.33ms,频率约为1/3.33ms=300.3Hz
  187.                         time_pwm = 0;
  188.                 if(ab=='A')       //如果参数为A
  189.                 {
  190.                         MotorB = 0;   //则产生正脉冲,此时电机正转
  191.                         if(time_pwm < pwm)        //占空比为(pwm/10*100%),改变pwm值(范围0-10)即改变占空比(对应0-100%),从而可以改变电机的速度
  192.                                 MotorA = 1;
  193.                         else
  194.                                 MotorA = 0;
  195.                 }
  196.                 else if(ab=='B')  //如果参数为B
  197.                 {
  198.                         MotorA = 0;   //则产生负脉冲,此时电机反转
  199.                         if(time_pwm < pwm)        //占空比为(pwm/10*100%),改变pwm值(范围0-10)即改变占空比(对应0-100%),从而可以改变电机的速度
  200.                                 MotorB = 1;
  201.                         else
  202.                                 MotorB = 0;
  203.                 }
  204.         }
  205. }

  206. /*******定时器0中断******/
  207. void Time0(void) interrupt 1   
  208. {
  209.         TL0 = 0xCD;               
  210.         TH0 = 0xFE;      //重新赋初值333us,0.03%误差
  211.         time_pwm++;         
  212.         time_30s++;     //每333us进入一次中断,同时time_pwm、time_30s值各加一
  213. }
复制代码

所有资料51hei提供下载:
程序.zip (44.38 KB, 下载次数: 63)
回复

使用道具 举报

ID:1 发表于 2019-6-17 15:56 | 显示全部楼层
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
回复

使用道具 举报

ID:297748 发表于 2019-6-18 14:00 | 显示全部楼层
admin 发表于 2019-6-17 15:56
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)

我上传一个仿真图吧
回复

使用道具 举报

ID:324611 发表于 2019-8-12 10:19 | 显示全部楼层
好东西,学习下。
回复

使用道具 举报

ID:386216 发表于 2019-8-28 16:05 | 显示全部楼层
楼主有没原理图,谢谢
回复

使用道具 举报

ID:336378 发表于 2019-9-10 12:00 | 显示全部楼层
看看,能不能有用。
回复

使用道具 举报

ID:56665 发表于 2019-9-11 08:50 | 显示全部楼层
下载看了一下,牙刷里面就是一个电机,正转反转线路怎么接,还是要有原理图才清楚。
回复

使用道具 举报

ID:276663 发表于 2019-9-11 09:48 | 显示全部楼层
admin 发表于 2019-6-17 15:56
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)

管理员建议太好了
回复

使用道具 举报

ID:573089 发表于 2019-10-31 20:14 | 显示全部楼层
希望楼主能上传看看
回复

使用道具 举报

ID:386216 发表于 2019-11-15 15:24 | 显示全部楼层
楼主,程序我有看了,有问题啊,你都没有调动MotorControl(uchar pwm, uchar ab)这个函数
回复

使用道具 举报

ID:709319 发表于 2020-3-18 09:30 | 显示全部楼层
下下来研究研究!!!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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