找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于51单片机的平衡车源程序

[复制链接]
跳转到指定楼层
楼主
ID:855478 发表于 2021-1-8 16:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这份代码是国赛的时候用的,也算是一个豪华的平衡车,里面有很多算法值得初学者学习。
所有的输入设备建议加一个二极管

STC8G8K64S4主板IO分配推荐
编码器2个
DIR  P50
LSB CTIM0_P34

DIR  P51
LSB CTIM3_P04


ICM20602:
SPC    P25
SDI    P23
SDO    P24
CS    P27


SPI屏幕引脚:
SCL    P25
SDA    P23
RST    P32
DC    P33
CS    P35
BL    P36

2个电机:
P00
P01

P22
P26


线性CCD(第一个):
CLK: P20
SI:     P21
AO:P05

线性CCD(第二个):
CLK: P20
SI:     P21
AO:P06

单片机源程序如下:
  1. /********************* 节能管脚分配 *******************************************

  2. REST    P54   
  3. LED            P47
  4. LED            P15
  5. ---------------------------------------------------------------------------
  6. 下载口:
  7. R        P30
  8. T        P31
  9. UART3: 调试口
  10. R        P50
  11. T        P51
  12. UART4: 上位机
  13. R        P52
  14. T        P53
  15. ---------------------------------------------------------------------------
  16. 模拟MPU6050:
  17. SCL         P32
  18. SDA         P33
  19. MPUIT   
  20. ---------------------------------------------------------------------------
  21. ENCODER:
  22. L        DIR:P05     TIM3_CIN:P04         
  23. R        DIR:P07     TIM4_CIN:P06
  24. ---------------------------------------------------------------------------
  25. MOTOR_PWMXX: select P2
  26. L        P20  P21
  27. R        P22  P23
  28. 备用        P24  P25  P26        P27
  29. STC8A  一共1个PWM模块 可以输出8路频率相同的PWM波  这8路PWM每路可以映射在三个管脚上面       
  30. channel     n = 2     n = 1    n = 6
  31. PWM00       P2_0      P1_0     P6_0  
  32. PWM01       P2_1      P1_1     P6_1
  33. PWM02       P2_2      P1_2     P6_2
  34. PWM03       P2_3      P1_3     P6_3
  35. PWM04       P2_4      P1_4     P6_4
  36. PWM05       P2_5      P1_5     P6_5
  37. PWM06       P2_6      P1_6     P6_6
  38. PWM07       P2_7      P1_7     P6_7
  39. ---------------------------------------------------------------------------
  40. ADCX: select P1
  41. 0     P1.0         
  42. 1     P1.1        
  43. 2     P1.2         
  44. 3     P1.3         
  45. 4     P1.4         
  46. 5     P1.5
  47. 6          P1.6
  48. 7          P1.7
  49. SCT8G/STC8A 有15个ADC通道 每个通道对应管脚如下
  50. 0     P1.0          8  P0.0
  51. 1     P1.1          9  P0.1
  52. 2     P1.2          10 P0.2
  53. 3     P1.3          11 P0.3
  54. 4     P1.4          12 P0.4
  55. 5     P1.5          13 P0.5
  56. 6     P1.6          14 P0.6
  57. 7     P1.7          15 测试内部 1.19V
  58. ---------------------------------------------------------------------------
  59. INT:
  60. INT0        P32
  61. INT1        P33
  62. INT2        P36
  63. INT3        P37
  64. ---------------------------------------------------------------------------
  65. timer:
  66. timer0       
  67. timer1
  68. tiemr2        串口波特率发生器
  69. timer3        P37
  70. timer4  
  71. ---------------------------------------------------------------------------
  72. */
  73. #include "headfile.h"

  74. //board.h文件中FOSC设置内部晶振频率为35Mhz
  75. //使用stc-isp工具下载程序的时候需要将IRC频率设置为35Mhz

  76. int16 send[6];             //上位机数组
  77. int16 sec;                 //小车运行时间
  78. float power;               //电源的电压值
  79. char rec;                  //调试串口值
  80. float K1=0.04;                  //互补滤波加权值   注意:这里原始值是0.03,可能需要更改
  81. float Balance_Kp=600,Balance_Kd=-10,Velocity_Kp=-6,Velocity_Ki=-0.05;//PID参数
  82. float Angle_Balance,Gyro_Balance,Gyro_Turn; //平衡倾角 平衡陀螺仪 转向陀螺仪
  83. int Encoder_Left,Encoder_Right;             //左右编码器的脉冲计数
  84. long int Balance_Pwm,Velocity_Pwm,Turn_Pwm;      //直立环 速度环  转向环的pwm
  85. char delay_50,delay_flag;
  86. char oled_show,rtu_show;
  87. Inductance ppInductance;
  88. Inductance *psInductance;
  89. float Kp=30,Kd=12;  //转向环PD参数
  90. int Velocity_target;
  91. float zhongzhi;
  92. int distance_garage,distance_huandao;
  93. char flag,strong_flag,huandao_flag_num;
  94. float power_bili;
  95. char stop_flag;

  96. void main()
  97. {
  98.         RSTCFG = 0x50;      //自动下载和复位
  99.        
  100.         /**********数据初始化****************/
  101.         psInductance=&ppInductance;
  102.         stop_flag=0;
  103.         sec=0;
  104.   power=0;
  105.         rec='p';
  106.         Encoder_Left=Encoder_Right=0;
  107.         oled_show=1;
  108.         rtu_show=1;
  109.         Velocity_target=1000;
  110.         Velocity_Pwm=0;
  111.         zhongzhi=-6;
  112.         flag=2;
  113.         strong_flag=2;
  114.         distance_garage,distance_huandao=0;
  115.         psInductance->InductanceGYHC_MAX=0;
  116.   psInductance->dir_sum=0;
  117.         huandao_flag_num=0;
  118.         /***********************************/
  119.        
  120.         DisableGlobalIRQ();        //关闭总中断
  121.         board_init();                //初始化内部寄存器
  122.        
  123.        
  124.         /**********硬件外设初始化************/
  125.   gpio_mode(led1, GPO_PP);
  126.         gpio_mode(led2, GPO_PP);

  127.   gpio_mode(key1, GPI_IMPEDANCE);
  128.         gpio_mode(key2, GPI_IMPEDANCE);
  129.   gpio_mode(key3, GPI_IMPEDANCE);
  130.         gpio_mode(key4, GPI_IMPEDANCE);

  131.         gpio_mode(P00, GPI_IMPEDANCE);
  132.         gpio_mode(P01, GPI_IMPEDANCE);
  133.         gpio_mode(P02, GPI_IMPEDANCE);
  134.         gpio_mode(P03, GPI_IMPEDANCE);       
  135.         gpio_mode(P05, GPI_IMPEDANCE);
  136.         gpio_mode(P07, GPI_IMPEDANCE);
  137.         gpio_mode(P10, GPI_IMPEDANCE);
  138.         gpio_mode(P16, GPI_IMPEDANCE);
  139.        
  140.         gpio_mode(P04, GPI_IMPEDANCE);
  141.         gpio_mode(P34, GPI_IMPEDANCE);       
  142.        
  143.         gpio_mode(P06, GPI_IMPEDANCE);
  144.         gpio_mode(P35, GPI_IMPEDANCE);
  145.        
  146.         gpio_mode(P23, GPO_PP);
  147.         gpio_mode(P22, GPO_PP);
  148.         gpio_mode(P21, GPO_PP);
  149.         gpio_mode(P20, GPO_PP);
  150.         gpio_mode(P44, GPO_PP);

  151.         gpio_mode(PWM1_P11, GPO_PP);
  152.         gpio_mode(PWM1_P12, GPO_PP);
  153.         gpio_mode(PWM1_P13, GPO_PP);
  154.         gpio_mode(PWM1_P14, GPO_PP);
  155.        
  156.         pwm_init(PWM1_P11,500, 0);
  157.         pwm_init(PWM1_P12,500, 0);
  158.         pwm_init(PWM1_P13,500, 0);
  159.         pwm_init(PWM1_P14,500, 0);
  160.        
  161.         adc_init(ADC_P10,         ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  162.         adc_init(ADC_P00,         ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  163.         adc_init(ADC_P01,         ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  164.         adc_init(ADC_P02,         ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  165.         adc_init(ADC_P03,         ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  166.         adc_init(ADC_P05,         ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  167.         adc_init(ADC_P16,         ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  168.   mpu6050_init();
  169.         oled_init();
  170.        
  171.         ctimer_count_init(CTIM0_P34);       
  172.         ctimer_count_init(CTIM4_P06);       
  173.         //uart_init(UART_3, UART3_RX_P50,UART3_TX_P51, 115200, TIM_2);
  174.         uart_init(UART_4, UART4_RX_P52,UART4_TX_P53, 115200, TIM_2);
  175.        
  176.         /***********************************/
  177.        
  178.         /**********软件外设初始化************/       
  179.   exit_init(INT2_P36,FALLING_EDGE);
  180. //  exit_init(INT3_P37,FALLING_EDGE);       
  181.         pca_dealy_init();
  182. //        pca_init_interrupt_ms(PCA_0, 40);        //使用PCA_0作为周期中断,时间1ms一次
  183.   pit_timer_ms(TIM_1,10);                  //定时器1
  184.         /***********************************/       
  185.        
  186.         adc_init(ADC_P10,         ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  187.         adc_init(ADC_P00,          ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  188.         adc_init(ADC_P01,         ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  189.         adc_init(ADC_P02,         ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  190.         adc_init(ADC_P05,         ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  191.         adc_init(ADC_P16,         ADC_SYSclk_DIV_2);        //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2
  192.   while(power<6.4)
  193.         {
  194.           power=12.12*adc_once(ADC_P16, ADC_10BIT)/1050;
  195.           oled_printf_float(80,6,power,3,2);
  196.                 if(key1==0)    Velocity_target=130;
  197.                 if(key2==0)    Velocity_target=160;
  198.                 if(key3==0)    Velocity_target=200;
  199.         }
  200.        
  201. EnableGlobalIRQ();        //开启总中断       
  202.        
  203.     while(1)          //50ms一个精确循环
  204.         {               
  205.         if(oled_show==1)
  206.         {
  207.                 oled_uint16(0,0, psInductance->InductanceAveNowA);
  208.                 oled_uint16(0,1, psInductance->InductanceAveNowB);       
  209.                 oled_uint16(0,2, psInductance->InductanceAveNowC);       
  210.                 oled_uint16(0,3, psInductance->InductanceAveNowD);       
  211.                 oled_uint16(0,4, psInductance->InductanceAveNowE);               
  212.                 oled_int16(0,5, psInductance->dir);               
  213.                 oled_int16(0,6, mpu_acc_x/48);               
  214. //                oled_uint16(0,4, psInductance->InductanceAveNowE);
  215. //               
  216.                 oled_uint16(60,0, psInductance->InductanceGYHA);
  217.                 oled_uint16(60,1, psInductance->InductanceGYHB);
  218.                 oled_uint16(60,2, psInductance->InductanceGYHC);       
  219.                 oled_uint16(60,3, psInductance->InductanceGYHD);
  220.                 oled_uint16(60,4, psInductance->InductanceGYHE);
  221.     oled_uint16(60,5,flag);
  222.     oled_printf_float(60,6,power,3,2);
  223.         }
  224.         if(rtu_show==1)
  225.         {
  226.     send[0]=Velocity_Pwm;    //mpu_gyro_z
  227.                 send[1]=Balance_Pwm;
  228.                 send[2]=Encoder_Left;                
  229.                 send[3]=Encoder_Right;         //注意这是平衡方向的加速度计
  230.                 send[4]=Angle_Balance;         //注意这是平衡方向的加速度计
  231.           rtu_send_data(send,5);
  232.         }
  233.           if(rec=='A')
  234.                 {
  235.                         Balance_Kd+=0.5;
  236.                         rec='p';
  237.                 }
  238.                         if(rec=='B')
  239.                         {                       
  240.                         Balance_Kd-=0.5;
  241.                         rec='p';
  242.                         }
  243.                         delay_flag = 1;
  244.       delay_50   = 0;
  245.     while(delay_flag);
  246.   }
  247. }


  248. //三电感AC先比较判断偏左还是偏右  然后用左循迹AB或者右循迹BC差比和
复制代码

所有程序51hei提供下载:
8.12 2.2米.zip (863.79 KB, 下载次数: 57)


评分

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

查看全部评分

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

使用道具 举报

沙发
ID:295290 发表于 2023-4-13 15:46 | 只看该作者
感谢分享!要是有个原理图就完美了!
回复

使用道具 举报

板凳
ID:1091382 发表于 2023-9-4 18:13 | 只看该作者
全是代码,没有实物图怎么搞?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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