找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6353|回复: 29
收起左侧

用stc12可以做平衡车吗??

  [复制链接]
ID:223788 发表于 2018-3-24 22:38 | 显示全部楼层 |阅读模式
我之前用stc12做过,但是一直做不出来,请问你们有没有做过呢?是不是要用像adunio那样更高级的单片机才能做出来。能不能分享下经验。

评分

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

查看全部评分

回复

使用道具 举报

ID:1 发表于 2018-3-25 02:49 | 显示全部楼层
这个可以做,我看过别人做的例子

评分

参与人数 1黑币 +12 收起 理由
JACKLI + 12 淡定

查看全部评分

回复

使用道具 举报

ID:155507 发表于 2018-3-25 07:15 | 显示全部楼层
  1. /***********************************************************************
  2. // 两轮自平衡车最终版控制程序(6轴MPU6050+互补滤波+PWM电机)
  3. // 单片机STC12C5A60S2
  4. // 晶振:20M
  5. // 日期:2014.11.26 - ?
  6. ***********************************************************************/

  7. #include <REG52.H>
  8. #include <math.h>     
  9. #include <stdio.h>   
  10. #include <INTRINS.H>

  11. typedef unsigned char  uchar;
  12. typedef unsigned short ushort;
  13. typedef unsigned int   uint;

  14. //******功能模块头文件*******

  15. #include "DELAY.H"    //延时头文件
  16. //--------------------------------------------
  17. #include "STC_ISP.H"    //程序烧录头文件
  18. #include "SET_SERIAL.H"//串口头文件

  19. #include "SET_PWM.H"//PWM头文件
  20. #include "MOTOR.H"//电机控制头文件
  21. #include "MPU6050.H"//MPU6050头文件
  22. //-----------------这些文件---------------------------



  23. //******角度参数************

  24. float Gyro_y;        //Y轴陀螺仪数据暂存

  25. //--------------加速度和角度的转化------------------


  26. float Angle_gy;      //由角速度计算的倾斜角度
  27. //陀螺仪直接反应角度

  28. float Accel_x;     //X轴加速度值暂存
  29. float Angle_ax;      //由加速度计算的倾斜角度 、

  30. float Angle;         //小车最终倾斜角度
  31. uchar value; //角度正负极性标记

  32. //******PWM参数*************

  33. int   speed_mr; //右电机  转速//这个的测量---------转盘
  34. int   speed_ml; //左电机  转速
  35. int   PWM_R;         //右轮PWM值计算
  36. int   PWM_L;         //左轮PWM值计算
  37. float PWM;           //综合PWM计算
  38. float PWMI; //PWM积分值

  39. //******电机参数*************

  40. float speed_r_l;//电机转速
  41. float speed;        //电机转速滤波
  42. float position;    //位移

  43. //******蓝牙遥控参数*************
  44. uchar remote_char;
  45. char  turn_need;
  46. char  speed_need;

  47. //*********************************************************
  48. //定时器100Hz数据更新中断 T1定时器
  49. //*********************************************************

  50. void Init_Timer1(void)//10毫秒@20MHz,100Hz刷新频率
  51. {
  52.         AUXR &= 0xBF;//定时器时钟12T模式
  53.         TMOD &= 0x0F;//设置定时器模式
  54.         TMOD |= 0x10;//设置定时器模式
  55.         TL1 = 0xE5;    //设置定时初值
  56.         TH1 = 0xBE;    //设置定时初值
  57.         TF1 = 0;    //清除TF1标志
  58.         TR1 = 1;    //定时器1开始计时
  59. }



  60. //*********************************************************
  61. //中断控制初始化
  62. //*********************************************************

  63. void Init_Interr(void)
  64. {
  65.         EA = 1;     //开总中断
  66.         EX0 = 1;    //开外部中断INT0
  67.         EX1 = 1;    //开外部中断INT1
  68.         IT0 = 1;    //下降沿触发
  69.         IT1 = 1;    //下降沿触发
  70.         ET1 = 1;    //开定时器1中断
  71. }



  72. //******卡尔曼参数************

  73. float code Q_angle=0.001;  
  74. float code Q_gyro=0.003;
  75. float code R_angle=0.5;
  76. float code dt=0.01;                  //dt为kalman滤波器采样时间;
  77. char  code C_0 = 1;
  78. float xdata Q_bias, Angle_err;
  79. float xdata PCt_0, PCt_1, E;
  80. float xdata K_0, K_1, t_0, t_1;
  81. float xdata Pdot[4] ={0,0,0,0};
  82. float xdata PP[2][2] = { { 1, 0 },{ 0, 1 } };

  83. //*********************************************************
  84. // 卡尔曼滤波
  85. //*********************************************************

  86. //Kalman滤波,20MHz的处理时间约0.77ms;

  87. void Kalman_Filter(float Accel,float Gyro)  // 滤波,输出标准的方波驱动电机
  88. {
  89.         Angle+=(Gyro - Q_bias) * dt; //先验估计陀螺角度


  90.         Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // Pk-先验估计误差协方差的微分

  91.         Pdot[1]=- PP[1][1];
  92.         Pdot[2]=- PP[1][1];
  93.         Pdot[3]=Q_gyro;

  94.         PP[0][0] += Pdot[0] * dt;   // Pk-先验估计误差协方差微分的积分
  95.         PP[0][1] += Pdot[1] * dt;   // =先验估计误差协方差
  96.         PP[1][0] += Pdot[2] * dt;
  97.         PP[1][1] += Pdot[3] * dt;

  98.         Angle_err = Accel - Angle;//zk-先验估计

  99.         PCt_0 = C_0 * PP[0][0];
  100.         PCt_1 = C_0 * PP[1][0];

  101.         E = R_angle + C_0 * PCt_0;

  102.         K_0 = PCt_0 / E;
  103.         K_1 = PCt_1 / E;

  104.         t_0 = PCt_0;
  105.         t_1 = C_0 * PP[0][1];

  106.         PP[0][0] -= K_0 * t_0; //后验估计误差协方差
  107.         PP[0][1] -= K_0 * t_1;
  108.         PP[1][0] -= K_1 * t_0;
  109.         PP[1][1] -= K_1 * t_1;

  110.         Angle+= K_0 * Angle_err; //后验估计
  111.         Q_bias+= K_1 * Angle_err; //后验估计
  112.         Gyro_y   = Gyro - Q_bias; //输出值(后验估计)的微分=角速度

  113. }



  114. //*********************************************************
  115. // 倾角计算(卡尔曼融合)
  116. //*********************************************************

  117. void Angle_Calcu(void)
  118. {
  119.         //------加速度--------------------------

  120.         //范围为2g时,换算关系:16384 LSB/g
  121.         //角度较小时,x=sinx得到角度(弧度), deg = rad*180/3.14
  122.         //因为x>=sinx,故乘以1.3适当放大

  123.         Accel_x  = GetData(ACCEL_XOUT_H);  //读取X轴加速度         存在ACCEL_XOUT_H 寄存器
  124.         Angle_ax = (Accel_x - 1100) /16384;   //去除零点偏移,计算得到角度(弧度)
  125.         Angle_ax = Angle_ax*1.2*180/3.14;     //弧度转换为度,


  126.         //-------角速度-------------------------

  127.         //范围为2000deg/s时,换算关系:16.4 LSB/(deg/s)

  128.         Gyro_y = GetData(GYRO_YOUT_H);      //静止时角速度Y轴输出为  【-30】 左右
  129.         Gyro_y = -(Gyro_y + 30)/16.4;         //去除零点偏移,计算角速度值,  【负号为方向处理】
  130.         //Angle_gy = Angle_gy + Gyro_y*0.01;  //角速度积分得到倾斜角度.


  131.         //-------卡尔曼滤波融合-----------------------

  132.         Kalman_Filter(Angle_ax,Gyro_y);       //卡尔曼滤波计算倾角


  133.         /*//-------互补滤波-----------------------

  134. //补偿原理是取当前倾角和加速度获得倾角差值进行放大,然后与
  135.         //陀螺仪角速度叠加后再积分,从而使倾角最跟踪为加速度获得的角度
  136. //0.5为放大倍数,可调节补偿度;0.01为系统周期10ms

  137. Angle = Angle + (((Angle_ax-Angle)*0.5 + Gyro_y)*0.01);*/

  138. }  



  139. //*********************************************************
  140. //电机转速和位移值计算
  141. //*********************************************************

  142. void Psn_Calcu(void)
  143. {

  144.         speed_r_l =(speed_mr + speed_ml)*0.5;
  145.         speed *= 0.7;//上一次的                  //车轮速度滤波
  146.         speed += speed_r_l*0.3;
  147.         position += speed;                  //积分得到位移
  148.         position += speed_need;//加上蓝牙位移,等于总的移动
  149.         if(position<-6000) position = -6000;
  150.         if(position> 6000) position =  6000;


  151. }


  152. static float code Kp  = 9.0;       //PID参数
  153. static float code Kd  = 2.6;    //PID参数
  154. static float code Kpn = 0.01;      //PID参数
  155. static float code Ksp = 2.0;    //PID参数

  156. //*********************************************************
  157. //电机PWM值计算
  158. //*********************************************************

  159. void PWM_Calcu(void)
  160. {

  161.         if(Angle<-40||Angle>40)               //角度过大,关闭电机
  162.         {  
  163.                 CCAP0H = 0;
  164.                 CCAP1H = 0;
  165.                 return;
  166.         }
  167.         PWM  = Kp*Angle + Kd*Gyro_y;          //PID:角速度和角度
  168.         PWM += Kpn*position + Ksp*speed;      //PID:速度和位置
  169.         PWM_R = PWM + turn_need;
  170.         PWM_L = PWM - turn_need;   //蓝牙的倾斜,
  171.         PWM_Motor(PWM_L,PWM_R);

  172. }




  173. //*********************************************************
  174. //手机蓝牙遥控
  175. //*********************************************************

  176. void Bluetooth_Remote(void)
  177. {

  178.         remote_char = receive_char();   //接收蓝牙串口数据

  179.         if(remote_char ==0x02) speed_need = -80;   //前进
  180.         else if(remote_char ==0x01) speed_need = 80;   //后退
  181.         else speed_need = 0;   //不动

  182.         if(remote_char ==0x03) turn_need = 15;   //左转
  183.         else if(remote_char ==0x04) turn_need = -15;   //右转
  184.         else turn_need = 0;   //不转

  185. }


  186. /*=================================================================================*/

  187. //*********************************************************
  188. //main
  189. //*********************************************************
  190. void main()
  191. {

  192.         delaynms(500);   //上电延时
  193.         Init_PWM();       //PWM初始化
  194.         Init_Timer0();     //初始化定时器0,作为PWM时钟源
  195.         Init_Timer1();     //初始化定时器1
  196.         Init_Interr();     //中断初始化
  197.         Init_Motor();   //电机控制初始化
  198.         Init_BRT();   //串口初始化(独立波特率)
  199.         InitMPU6050();     //初始化MPU6050
  200.         delaynms(500);   

  201.         while(1)
  202.         {

  203.                 Bluetooth_Remote();

  204.         }
  205. }


  206. /*=================================================================================*/

  207. //********timer1中断***********************

  208. void Timer1_Update(void) interrupt 3
  209. {

  210.         TL1 = 0xE5;    //设置定时初值10MS
  211.         TH1 = 0xBE;

  212.         //STC_ISP();                    //程序下载
  213.         Angle_Calcu();                  //倾角计算
  214.         Psn_Calcu();                    //电机位移计算
  215.         PWM_Calcu();                    //计算PWM值

  216.         speed_mr = speed_ml = 0;

  217. }


  218. //********右电机中断***********************

  219. void INT_L(void) interrupt 0
  220. {

  221.         if(SPDL == 1)  { speed_ml++; } //左电机前进
  222.         else      { speed_ml--; } //左电机后退
  223.         LED = ~LED;

  224. }


  225. //********左电机中断***********************

  226. void INT_R(void) interrupt 2
  227. {

  228.         if(SPDR == 1)  { speed_mr++; } //右电机前进
  229.         else      { speed_mr--; } //右电机后退
  230.         LED = ~LED;

  231. }

复制代码

评分

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

查看全部评分

回复

使用道具 举报

ID:296601 发表于 2018-3-25 09:09 | 显示全部楼层
可以做啊

评分

参与人数 1黑币 +3 收起 理由
JACKLI + 3 淡定

查看全部评分

回复

使用道具 举报

ID:278349 发表于 2018-3-25 09:11 | 显示全部楼层
可以做,可以参考STC官网的一些程序

评分

参与人数 1黑币 +6 收起 理由
JACKLI + 6 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:296160 发表于 2018-3-25 09:16 | 显示全部楼层
可以做的,Arduino是单片机二次开发的产物。普通单片机只是散件,硬件的设计和软件设计都得你自己来。而且arduino是半成品,你只要把相应的模块组合在一起,再写一写甚至直接复制别人程序就能行了。

评分

参与人数 1黑币 +10 收起 理由
JACKLI + 10 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:223788 发表于 2018-3-25 09:58 | 显示全部楼层

可以不可以分享一下你的经验?
回复

使用道具 举报

ID:223788 发表于 2018-3-25 10:00 | 显示全部楼层

这是你自己写的代码吗?
回复

使用道具 举报

ID:223788 发表于 2018-3-25 10:01 | 显示全部楼层
admin 发表于 2018-3-25 02:49
这个可以做,我看过别人做的例子

噢 噢 噢 。
回复

使用道具 举报

ID:223788 发表于 2018-3-25 10:02 | 显示全部楼层
luohe2010 发表于 2018-3-25 09:11
可以做,可以参考STC官网的一些程序

好,等下过去看看
回复

使用道具 举报

ID:223788 发表于 2018-3-25 10:13 | 显示全部楼层
21陈小羊 发表于 2018-3-25 09:16
可以做的,Arduino是单片机二次开发的产物。普通单片机只是散件,硬件的设计和软件设计都得你自己来。而且a ...

是啊,我看别人做平衡车大多都是用arduino做的,用51做的人很少,我之前找资料都很难找到,然后就一直到现在还没弄好。。。。
回复

使用道具 举报

ID:295133 发表于 2018-3-25 11:04 | 显示全部楼层
能不能分享下经验。
回复

使用道具 举报

ID:296648 发表于 2018-3-25 11:47 | 显示全部楼层
可以,论坛里应该有资料

评分

参与人数 1黑币 +3 收起 理由
JACKLI + 3 淡定

查看全部评分

回复

使用道具 举报

ID:294737 发表于 2018-3-25 16:21 | 显示全部楼层
可以,你可以看一下正点原子的教程

评分

参与人数 1黑币 +8 收起 理由
JACKLI + 8 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:274129 发表于 2018-3-25 17:03 | 显示全部楼层
嗯  可以的只要是代码的问题

评分

参与人数 1黑币 +6 收起 理由
JACKLI + 6 赞一个!

查看全部评分

回复

使用道具 举报

ID:223788 发表于 2018-3-25 20:05 | 显示全部楼层
wcwt560 发表于 2018-3-25 11:47
可以,论坛里应该有资料

好的
回复

使用道具 举报

ID:223788 发表于 2018-3-25 20:06 | 显示全部楼层
muxu 发表于 2018-3-25 16:21
可以,你可以看一下正点原子的教程

嗯嗯   ,好的
回复

使用道具 举报

ID:223788 发表于 2018-3-25 21:10 | 显示全部楼层
爱爱爱 发表于 2018-3-25 17:03
嗯  可以的只要是代码的问题

对啊! 那些PID算法看得头晕,然后就很绝望了
回复

使用道具 举报

ID:223788 发表于 2018-3-25 23:38 | 显示全部楼层

可以分享一下头文件吗?
回复

使用道具 举报

ID:155507 发表于 2018-3-26 21:11 | 显示全部楼层
  1. /*--------------------------------------------------------------------------
  2. DELAY.H

  3. 延时函数 头文件
  4. --------------------------------------------------------------------------*/

  5. #ifndef __DELAY_H__
  6. #define __DELAY_H__

  7. #define uchar unsigned char
  8. #define uint  unsigned int


  9. //------函数(声明)--------------------------------
  10. void Delay400Ms(void);        //延时400mS函数(子程序)
  11. void delay1ms(void);        //延时1mS函数(子程序)
  12. void delaynms(uchar n);    //延时n mS函数(子程序)



  13. //***********************************************************************************/
  14. //延时400ms

  15. void Delay400Ms(void)
  16. {

  17.         uchar TempCycA = 30;//1周期MPU用30,  12周期MPU用5
  18.         uint TempCycB;
  19.         while(TempCycA--)
  20.         {

  21.                 TempCycB=7269;
  22.                 while(TempCycB--);

  23.         };

  24. }



  25. //***********************************************************************************/
  26. //延时1ms

  27. void delay1ms()
  28. {

  29.         uchar i,j;
  30.         for(i=0;i<10;i++)
  31.                 for(j=0;j<33;j++)
  32.                 ;

  33. }



  34. //***********************************************************************************/
  35. //延时n*ms

  36. void delaynms(uchar n)
  37. {

  38.         uchar i;
  39.         for(i=0;i<n;i++) delay1ms();


  40. }

  41. #endif

复制代码

  1. /*****************************************************

  2. 普通IO模拟I2C通信
  3. STC12C5A60S2  IT单片机   AXTL;11.0592MHz

  4. *****************************************************/

  5. #ifndef  __I2C_H__
  6. #define  __I2C_H__


  7. #include <REG52.H>
  8. #include <math.h>    //Keil library  
  9. #include <stdio.h>   //Keil library
  10. #include <INTRINS.H>



  11. //********端口定义**********************************
  12. sbit    SCL=P2^1;//IIC时钟引脚定义
  13. sbit    SDA=P2^0;//IIC数据引脚定义

  14. #defineSlaveAddress 0xD0   //IIC写入时的地址字节数据,+1为读取


  15. //********函数初始定义******************************
  16. void  Delay5us();
  17. void  I2C_Start();
  18. void  I2C_Stop();
  19. void  I2C_SendACK(bit ack);
  20. bit   I2C_RecvACK();
  21. void  I2C_SendByte(uchar dat);
  22. uchar I2C_RecvByte();
  23. void  I2C_ReadPage();
  24. void  I2C_WritePage();
  25. void  display_ACCEL_x();
  26. void  display_ACCEL_y();
  27. void  display_ACCEL_z();
  28. uchar Single_ReadI2C(uchar REG_Address);//读取I2C数据
  29. void  Single_WriteI2C(uchar REG_Address,uchar REG_data);    //向I2C写入数据





  30. //**************************************
  31. //延时5微秒(STC12C5A60S2@12M)
  32. //不同的工作环境,需要调整此函数
  33. //此延时函数是使用1T的指令周期进行计算,与传统的12T的MCU不同
  34. //**************************************/
  35. void Delay5us()
  36. {

  37.         uchar n = 4;

  38.         while (n--)
  39.         {

  40.                 _nop_();
  41.                 _nop_();
  42.                
  43.         }

  44. }



  45. //**************************************
  46. //I2C起始信号
  47. //**************************************
  48. void I2C_Start()
  49. {

  50.         SDA = 1;                    //拉高数据线
  51.         SCL = 1;                    //拉高时钟线
  52.         Delay5us();                 //延时
  53.         SDA = 0;                    //产生下降沿
  54.         Delay5us();                 //延时
  55.         SCL = 0;                    //拉低时钟线

  56. }



  57. //**************************************
  58. //I2C停止信号
  59. //**************************************
  60. void I2C_Stop()
  61. {

  62.         SDA = 0;                    //拉低数据线
  63.         SCL = 1;                    //拉高时钟线
  64.         Delay5us();                 //延时
  65.         SDA = 1;                    //产生上升沿
  66.         Delay5us();                 //延时

  67. }



  68. //**************************************
  69. //I2C发送应答信号
  70. //入口参数:ack (0:ACK 1:NAK)
  71. //**************************************
  72. void I2C_SendACK(bit ack)
  73. {

  74.         SDA = ack;                  //写应答信号
  75.         SCL = 1;                    //拉高时钟线
  76.         Delay5us();                 //延时
  77.         SCL = 0;                    //拉低时钟线
  78.         Delay5us();                 //延时

  79. }



  80. //**************************************
  81. //I2C接收应答信号
  82. //**************************************
  83. bit I2C_RecvACK()
  84. {

  85.         SCL = 1;                    //拉高时钟线
  86.         Delay5us();                 //延时
  87.         CY = SDA;                   //读应答信号
  88.         SCL = 0;                    //拉低时钟线
  89.         Delay5us();                 //延时
  90.         return CY;

  91. }



  92. //**************************************
  93. //向I2C总线发送一个字节数据
  94. //**************************************
  95. void I2C_SendByte(uchar dat)
  96. {

  97.         uchar i;
  98.         for (i=0; i<8; i++)         //8位计数器
  99.         {

  100.                 dat <<= 1;              //移出数据的最高位
  101.                 SDA = CY;               //送数据口
  102.                 SCL = 1;                //拉高时钟线
  103.                 Delay5us();             //延时
  104.                 SCL = 0;                //拉低时钟线
  105.                 Delay5us();             //延时
  106.                
  107.         }
  108.         I2C_RecvACK();

  109. }


  110. //**************************************
  111. //从I2C总线接收一个字节数据
  112. //**************************************
  113. uchar I2C_RecvByte()
  114. {

  115.         uchar i;
  116.         uchar dat = 0;
  117.         SDA = 1;                    //使能内部上拉,准备读取数据,
  118.         for (i=0; i<8; i++)         //8位计数器
  119.         {

  120.                 dat <<= 1;
  121.                 SCL = 1;                //拉高时钟线
  122.                 Delay5us();             //延时
  123.                 dat |= SDA;             //读数据               
  124.                 SCL = 0;                //拉低时钟线
  125.                 Delay5us();             //延时
  126.                
  127.         }
  128.         return dat;

  129. }



  130. //**************************************
  131. //向I2C设备写入一个字节数据
  132. //**************************************
  133. void Single_WriteI2C(uchar REG_Address,uchar REG_data)
  134. {

  135.         I2C_Start();                  //起始信号
  136.         I2C_SendByte(SlaveAddress);   //发送设备地址+写信号
  137.         I2C_SendByte(REG_Address);    //内部寄存器地址
  138.         I2C_SendByte(REG_data);       //内部寄存器数据
  139.         I2C_Stop();                   //发送停止信号

  140. }



  141. //**************************************
  142. //从I2C设备读取一个字节数据
  143. //**************************************
  144. uchar Single_ReadI2C(uchar REG_Address)
  145. {

  146.         uchar REG_data;
  147.         I2C_Start();                   //起始信号
  148.         I2C_SendByte(SlaveAddress);    //发送设备地址+写信号
  149.         I2C_SendByte(REG_Address);     //发送存储单元地址,从0开始
  150.         I2C_Start();                   //起始信号
  151.         I2C_SendByte(SlaveAddress+1);  //发送设备地址+读信号
  152.         REG_data=I2C_RecvByte();       //读出寄存器数据
  153.         I2C_SendACK(1);                //接收应答信号
  154.         I2C_Stop();                    //停止信号
  155.         return REG_data;

  156. }


  157. #endif

复制代码

  1. /*********************************************************
  2. STC_12C5A60S2免断电烧录程序
  3. *********************************************************/


  4. #ifndef   _STC_ISP_H_
  5. #define   _STC_ISP_H_



  6. #include<REG52.h>

  7. sfr IAP_CONTR   = 0xC7; //IAP Control Register

  8. sbit  IN_OFF=P3^0;//串口接收端



  9. //**************************************************

  10. void STC_ISP()
  11. {

  12.        
  13.         IN_OFF=1; //――2

  14.         if(!IN_OFF){
  15.                 IAP_CONTR=0x60;
  16.         } //判断串口是否有数据过来


  17. }


  18. #endif

复制代码

  1. /**********************************************************************
  2. 串口收发程序(头文件)
  3. 波特率:9600Hz
  4. 可选定时器1或独立波特率作为串口时钟
  5. **********************************************************************/


  6. #ifndef __SET_SERIAL_H__
  7. #define __SET_SERIAL_H__


  8. sfr AUXR = 0x8E;
  9. sfr BRT = 0x9C;


  10. //***********************************************************************************/
  11. //定时器1初始化
  12. /*void Init_Timer1()
  13. {

  14.         // set timer1 mode
  15. TMOD |= 0x20;    //设置timer1为8位自动重载模式
  16. SCON = 0x50;     // 设定串行口工作方式
  17. PCON &= 0xef; // 波特率不倍增
  18. TH1=TL1=0xFD; //9600 Hz
  19. TR1 = 1; //开启Timer1


  20. }*/



  21. //***********************************************************************************/
  22. //独立波特率初始化

  23. void Init_BRT()////9600bps@20MHz
  24. {


  25.         PCON &= 0x7F;//波特率不倍速
  26.         SCON = 0x50;    //8位数据,可变波特率
  27.         AUXR |= 0x04;//独立波特率发生器时钟为Fosc,即1T
  28.         BRT = 0xBF;    //设定独立波特率发生器重装值
  29.         AUXR |= 0x01;//串口1选择独立波特率发生器为波特率发生器
  30.         AUXR |= 0x10;//启动独立波特率发生器


  31. }



  32. //***********************************************************************************/
  33. //串口接收程序

  34. receive_char() //receive data
  35. {

  36.         unsigned char rxd;
  37.         if(RI)     
  38.         {

  39.                 RI = 0;
  40.                 rxd = SBUF;
  41.                 return(rxd);

  42.         }

  43. }



  44. //***********************************************************************************/
  45. //串口发送子程序

  46. void send_char(unsigned char txd) //sent out data
  47. {

  48.         SBUF = txd;
  49.         while(!TI);
  50.         TI = 0;

  51. }



  52. #endif

复制代码


  1. /*********************************************************************************************

  2.     两路PWM输出控制设置

  3. /*********************************************************************************************/

  4. #ifndef __SET_PWM_H__
  5. #define __SET_PWM_H__


  6. //Declare SFR associated with the PCA

  7. sfr   CCON    = 0xD8;      //PCA control register
  8. sbit  CCF0    = CCON^0;    //PCA module-0 interrupt flag
  9. sbit  CCF1    = CCON^1;    //PCA module-1 interrupt flag
  10. sbit  CR      = CCON^6;    //PCA timer run control bit
  11. sbit  CF      = CCON^7;    //PCA timer overflow flag
  12. sfr   CMOD    = 0xD9;      //PCA mode register
  13. sfr   CL      = 0xE9;      //PCA base timer LOW
  14. sfr   CH      = 0xF9;      //PCA base timer HIGH
  15. sfr   CCAPM0  = 0xDA;      //PCA module-0 mode register
  16. sfr   CCAP0L  = 0xEA;      //PCA module-0 capture register LOW
  17. sfr   CCAP0H  = 0xFA;      //PCA module-0 capture register HIGH
  18. sfr   CCAPM1  = 0xDB;      //PCA module-1 mode register
  19. sfr   CCAP1L  = 0xEB;      //PCA module-1 capture register LOW
  20. sfr   CCAP1H  = 0xFB;      //PCA module-1 capture register HIGH
  21. sfr   PCAPWM0 = 0xf2;
  22. sfr   PCAPWM1 = 0xf3;



  23. //***********************************************************************************/
  24. //PWM模式设置

  25. void Init_PWM()
  26. {

  27.    // set PWM mode
  28.   CCON = 0;                  //Initial PCA control register(PCA timer stop,Clear CF flag,Clear all module interrupt flag)
  29.   CL = 0;                    //Reset PCA base timer
  30.   CH = 0;
  31.   CMOD = 0x04;               //Set PCA timer clock source as timer0 overflow,Disable PCA timer overflow interrupt
  32.   CCAP0H = CCAP0L = 255;     //PWM0 port output X% duty cycle square wave
  33.   CCAPM0 = 0x42;             //PCA module-0 work in 8-bit PWM mode and no PCA interrupt
  34.   CCAP1H = CCAP1L = 255;     //PWM1 port output X% duty cycle square wave
  35.   CCAPM1 = 0x42;             //PCA module-1 work in 8-bit PWM mode and no PCA interrupt
  36.   CR = 1;                    //PCA timer start run
  37.   
  38. }



  39. //***********************************************************************************/
  40. //设置Timer0为8位自动重载模式,作为PWM时钟源

  41. void Init_Timer0()
  42. {

  43.     // set timer0 mode
  44.   AUXR = 0x00;               //timer0 work in 12T mode
  45.   TMOD|= 0x02;    //set timer0 counter mode2 (8-bit auto-reload)
  46.   TH0=TL0=130; //PWM 50Hz
  47.   TR0 = 1; //timer0 start running(as PWM clk)

  48.    
  49. }



  50. #endif

复制代码

  1. /****************************************

  2. 平衡车两路直流减速电机PWM控制

  3. ****************************************/


  4. #ifndef__MOTOR_H__
  5. #define __MOTOR_H__

  6. #include <REG52.H>
  7. #include "SET_PWM.H"//PWM头文件


  8. //电机PWM控制端口定义
  9. sbit LED = P0^0;  //LED
  10. sbit EN12 = P1^3;     //L298电机(左)驱动使能
  11. sbit EN34 = P1^4;     //L298电机(右)驱动使能
  12. sbit M1= P1^1;  //电机驱动(M1=1,M2=0,右电机后退)
  13. sbit M2= P1^2;  //电机驱动(M1=0,M2=1,右电机前进)
  14. sbit M3= P1^5;  //电机驱动(M3=1,M4=0,左电机前进)
  15. sbit M4= P1^0;  //电机驱动(M3=0,M4=1,左电机后退)

  16. sbit SPDR = P3^4; //右电机B相测速,用来判断电机转向
  17. sbit SPDL = P3^5; //左电机B相测速,用来判断电机转向

  18. //变量定义
  19. bit flg_direc;  //电机运动方向标志



  20. /*********函数区************************/

  21. //**************************************
  22. //电机初始化
  23. //**************************************
  24. void Init_Motor()
  25. {

  26.    CCAP0H = 255;      //关闭PWM0输出
  27.    CCAP1H = 255;      //关闭PWM1输出
  28.    EN12 = 0;  //关闭左电机
  29.    EN34 = 0;  //关闭右电机

  30. }



  31. //**************************************
  32. //电机控制
  33. //**************************************
  34. void PWM_Motor(int pwm_l,int pwm_r)
  35. {


  36.    if(pwm_l<0)
  37.    {

  38.      M1 = 1;      //右电机后退
  39.      M2 = 0;
  40. pwm_l = -pwm_l;

  41. }
  42.    else
  43.    {

  44.      M1 = 0;      //右电机前进
  45.      M2 = 1;

  46. }

  47. if(pwm_r<0)
  48.    {

  49.      M3 = 0;      //左电机后退
  50.      M4 = 1;
  51. pwm_r = -pwm_r;

  52. }
  53.    else
  54.    {

  55.      M3 = 1;      //左电机前进
  56.      M4 = 0;
  57.   

  58. }

  59.    if(pwm_l>255)  pwm_l = 255 ;    //防止PWM值超过255
  60.    if(pwm_r>255)  pwm_r = 255 ;    //防止PWM值超过255
  61.    
  62.    CCAP0H = 0 + pwm_l;     //设定PWM0占空比(CCAP0H=255,速度最大)
  63.    CCAP1H = 0 + pwm_r;     //设定PWM1占空比(CCAP0H=255,速度最大)

  64.    //这里50可调,作用是跳过电机PWM死区,在PWM值为0-40时,电机不转动,即死区(**错误的注释,解释在下句*)
  65.    //*此处曾经完全被误导,曾经在0的地方加的是50,目的是为了消除电机PWM死区,但是导致小车严重震荡,现在该为零才对

  66. }

  67. #endif

复制代码


  1. /*********************************************

  2. MPU-6050数据处理

  3. *********************************************/


  4. #ifndef  _MPU6050_H_
  5. #define  _MPU6050_H_

  6. #include <REG52.H>
  7. #include <INTRINS.H>

  8. #include "I2C.H"



  9. //****************************************
  10. // 定义MPU6050内部地址
  11. //****************************************

  12. #defineSMPLRT_DIV0x19//陀螺仪采样率,典型值:0x07(125Hz)
  13. #defineCONFIG0x1A//低通滤波频率,典型值:0x06(5Hz)
  14. #defineGYRO_CONFIG0x1B//陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
  15. #defineACCEL_CONFIG0x1C//加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
  16. #defineACCEL_XOUT_H0x3B
  17. #defineACCEL_XOUT_L0x3C
  18. #defineACCEL_YOUT_H0x3D
  19. #defineACCEL_YOUT_L0x3E
  20. #defineACCEL_ZOUT_H0x3F
  21. #defineACCEL_ZOUT_L0x40
  22. #defineTEMP_OUT_H0x41
  23. #defineTEMP_OUT_L0x42
  24. #defineGYRO_XOUT_H0x43
  25. #defineGYRO_XOUT_L0x44
  26. #defineGYRO_YOUT_H0x45
  27. #defineGYRO_YOUT_L0x46
  28. #defineGYRO_ZOUT_H0x47
  29. #defineGYRO_ZOUT_L0x48
  30. #definePWR_MGMT_10x6B//电源管理,典型值:0x00(正常启用)
  31. #defineWHO_AM_I0x75//IIC地址寄存器(默认数值0x68,只读)
  32. //#defineSlaveAddress 0xD0   //IIC写入时的地址字节数据,+1为读取



  33. //MPU6050操作函数声明

  34. void  InitMPU6050();    //初始化MPU6050
  35. int GetData(uchar REG_Address);        //16位数据合成





  36. //**************************************
  37. //初始化MPU6050
  38. //**************************************
  39. void InitMPU6050()
  40. {

  41.         Single_WriteI2C(PWR_MGMT_1, 0x00);//解除休眠状态
  42.         Single_WriteI2C(SMPLRT_DIV, 0x07);
  43.         Single_WriteI2C(CONFIG, 0x06);
  44.         Single_WriteI2C(GYRO_CONFIG, 0x18);
  45.         Single_WriteI2C(ACCEL_CONFIG, 0x01);

  46. }



  47. //**************************************
  48. //合成数据
  49. //**************************************
  50. int GetData(uchar REG_Address)
  51. {

  52.         uint H;
  53.         uchar L;
  54.         H=Single_ReadI2C(REG_Address);
  55.         L=Single_ReadI2C(REG_Address+1);
  56.         return (H<<8)+L;   //合成数据

  57. }


  58. #endif

复制代码

评分

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

查看全部评分

回复

使用道具 举报

ID:223788 发表于 2018-3-26 23:42 | 显示全部楼层
回复

使用道具 举报

ID:297363 发表于 2018-3-27 10:32 | 显示全部楼层
应该是可以做的

评分

参与人数 1黑币 +5 收起 理由
JACKLI + 5 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:298036 发表于 2018-3-27 22:01 | 显示全部楼层
可以啊,不过平衡车对实时性要求有点高哦

评分

参与人数 1黑币 +6 收起 理由
JACKLI + 6 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:223788 发表于 2018-3-27 23:37 | 显示全部楼层
xue9695 发表于 2018-3-27 10:32
应该是可以做的

嗯,是可以的
回复

使用道具 举报

ID:223788 发表于 2018-3-27 23:38 | 显示全部楼层
qwertyuiop[ 发表于 2018-3-27 22:01
可以啊,不过平衡车对实时性要求有点高哦

对的啊,稳定性比较差了一点
回复

使用道具 举报

ID:298088 发表于 2018-3-28 00:30 | 显示全部楼层
肯定是可以的 淘宝有卖的吧

评分

参与人数 1黑币 +7 收起 理由
JACKLI + 7 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:223788 发表于 2018-3-28 22:36 | 显示全部楼层
heng123 发表于 2018-3-28 00:30
肯定是可以的 淘宝有卖的吧

某宝的平衡车太贵啦
回复

使用道具 举报

ID:299646 发表于 2018-3-30 21:00 | 显示全部楼层
stm32应该没有问题的,msp430也不错

评分

参与人数 1黑币 +5 收起 理由
JACKLI + 5 淡定

查看全部评分

回复

使用道具 举报

ID:223788 发表于 2018-3-31 09:41 | 显示全部楼层

我给单片机烧了你给的代码,也修改一些相应的端口,但是不管怎么倾斜移动平衡车,电机完全不会动,连接上了蓝牙也完全没反应,这是怎么回事 ?是不是还少了什么东西 ?
回复

使用道具 举报

ID:223788 发表于 2018-3-31 12:27 | 显示全部楼层
liunian00 发表于 2018-3-30 21:00
stm32应该没有问题的,msp430也不错

没有msp430,没有用过 这种芯片啊
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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