单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

新手入手carzepony四轴飞行器,有点没头绪,求大神指导

[复制链接]
跳转到指定楼层
楼主
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 转播转播 分享分享 分享淘帖 顶 踩
沙发
f556 发表于 2019-9-13 09:40 | 只看该作者
多想想有就头绪了,我做2.4G摇控就是这样的。
板凳
angmall 发表于 2019-9-14 07:15 | 只看该作者
我给你来个驱动航模用的无传感器无刷三相直流马达程序



  1. /*---------------------------------------------------------------------*/
  2. /* --- STC MCU International Limited ----------------------------------*/
  3. /* --- STC 1T Series MCU Demo Programme -------------------------------*/
  4. /* --- Mobile: 13922805190 --------------------------------------------*/
  5. /* --- Fax: 0513-55012956,55012947,55012969 ---------------------------*/
  6. /* --- Tel: 0513-55012928,55012929,55012966 ---------------------------*/
  7. /* --- Web: www.GXWMCU.com   www.stcmcu.com ---------------------------*/
  8. /* --- QQ:  800003751 -------------------------------------------------*/
  9. /* 如果要在程序中使用此代码,请在程序中注明使用了宏晶科技的资料及程序   */
  10. /*---------------------------------------------------------------------*/


  11. /*************        功能说明        **************

  12. 本程序试验使用STC15W401AS-35I-SOP16<RMB1.6>来驱动航模用的无传感器无刷三相直流马达.

  13. 本程序参考自网上的代码(作者: 瑞生), 改良而来.

  14. 电路图见文件 "BLDC-V10-实验电路.pdf".

  15. 控制信号由P3.2输入正脉冲信号, 间隔5~20ms, 脉冲宽度1.000~1.610ms.

  16. 1.160ms开始启动, 1.610ms为最高速度, 分辨率为2us.

  17. 本程序仅仅是简单控制, 软件没有处理 过0延时30度切换 过流检测.

  18. 由于过0检测部分有RC滤波, 所以改变电容值可以大约的对应在最高速时延时30度的时间.

  19. 有意者可自行完善电路和程序.

  20. ******************************************/




  21. #define MAIN_Fosc                24000000L        //定义主时钟

  22. #include "STC15Fxxxx.H"

  23. #define                MCU_PIN                16        /* 选择MCU引脚数, 只支持16或20脚(28脚或32脚跟20脚一样) */



  24. //CMPCR1
  25. #define        CMPEN        0x80        //1: 允许比较器, 0: 禁止,关闭比较器电源
  26. #define        CMPIF        0x40        //比较器中断标志, 包括上升沿或下降沿中断, 软件清0
  27. #define        PIE                0x20        //1: 比较结果由0变1, 产生上升沿中断
  28. #define        NIE                0x10        //1: 比较结果由1变0, 产生下降沿中断
  29. #define        PIS                0x08        //输入正极性选择, 0: 选择外部P5.5做正输入,           1: 由ADCIS[2:0]所选择的ADC输入端做正输入.
  30. #define        NIS                0x04        //输入负极性选择, 0: 选择内部BandGap电压BGv做负输入, 1: 选择外部P5.4做输入.
  31. #define        CMPOE        0x02        //1: 允许比较结果输出到P1.2, 0: 禁止.
  32. #define        CMPRES        0x01        //比较结果, 1: CMP+电平高于CMP-,  0: CMP+电平低于CMP-,  只读

  33. //CMPCR2
  34. #define        INVCMPO        0x80        //1: 比较器输出取反,  0: 不取反
  35. #define        DISFLT        0x40        //1: 关闭0.1uF滤波,   0: 允许
  36. #define        LCDTY        0x00        //0~63, 比较结果变化延时周期数

  37. #if        (MCU_PIN == 20)
  38.         sbit PWM2_L = P3^4;
  39.         sbit PWM1_L = P3^5;
  40.         sbit PWM0_L = P3^6;
  41. #endif

  42. #if        (MCU_PIN == 16)
  43.         sbit PWM2_L = P5^5;
  44.         sbit PWM1_L = P3^3;
  45.         sbit PWM0_L = P3^6;
  46. #endif

  47. u8        Step;
  48. u8        PWM_Value; // 决定PWM占空比的值
  49. u16        RxPulseWide;
  50. bit        B_RxOk;
  51. bit        B_RUN;
  52. u8        PWW_Set;
  53. u8        cnt10ms;
  54. u8        Rx_cnt;
  55. u8        TimeOut;        //堵转超时

  56. #define DISABLE_CMP_INT CMPCR1 &= ~0X40                // 关闭比较器中断
  57. #define ENABLE_CMP_INT  CMPCR1 |= 0X40                // 打开比较器中断

  58. /*************************/

  59. void        Delay_n_ms(u8 dly)
  60. {
  61.         u16        j;
  62.         do
  63.         {
  64.                 j = MAIN_Fosc / 13000;        //延时1ms, 主程序在此节拍下运行
  65.                 while(--j)        ;
  66.         }while(--dly);
  67. }


  68. void delay_us(u8 us)
  69. {
  70.         do
  71.         {
  72.                 NOP(20);        //@24MHz
  73.         }
  74.         while(--us);
  75. }

  76. void StepXL(void) // 换相序列函数
  77. {
  78. switch(Step)
  79.   {
  80.    case 0:  // AB
  81.                         PWM0_L=0;        PWM2_L=0;
  82.                         CCAP0H = PWM_Value;        CCAP1H=0;        CCAP2H=0;        // 打开A相的高端
  83.                         PWM1_L = 1;                 // 打开B相的低端
  84.                         ADC_CONTR = 0XED;        // 选择P1.5作为ADC输入 即c相电压
  85.                         CMPCR1 = 0x9C;                //bit7=1 允许比较器, bit4=1 比较结果由1变0, 产生下降沿中断 (不能响应下降沿中断?)
  86.                         break;
  87.    case 1:  // AC
  88.                         PWM0_L=0;        PWM1_L=0;
  89.                         CCAP0H = PWM_Value;        CCAP1H=0;        CCAP2H=0;        // 打开A相的高端
  90.                         PWM2_L = 1;                        // 打开C相的低端
  91.                         ADC_CONTR = 0XEC;        // 选择P1.4作为ADC输入 即B相电压
  92.                         CMPCR1 = 0xAC;                //上升沿中断
  93.          
  94.       break;
  95.    case 2:  // BC
  96.                         PWM0_L=0;        PWM1_L=0;
  97.                         CCAP0H=0;        CCAP2H=0;        CCAP1H = PWM_Value; // 打开B相的高端
  98.                         PWM2_L = 1;                        // 打开C相的低端
  99.                         ADC_CONTR = 0XEB;        // 选择P1.3作为ADC输入 即a相电压
  100.                         CMPCR1 = 0x9C;                //下降沿中断
  101.       break;
  102.    case 3:  // BA
  103.                         PWM1_L=0;        PWM2_L=0;
  104.                         CCAP0H=0;        CCAP2H=0;        CCAP1H = PWM_Value; // 打开B相的高端
  105.                         PWM0_L = 1;                        // 打开A相的低端
  106.                         ADC_CONTR = 0XED;        // 选择P1.5作为ADC输入 即c相电压
  107.                         CMPCR1 = 0xAC;                //上升沿中断
  108.                        
  109.       break;
  110.    case 4: // CA
  111.                         PWM1_L=0;        PWM2_L=0;
  112.                         CCAP0H=0;        CCAP1H=0;        CCAP2H = PWM_Value; // 打开C相的高端
  113.                         PWM0_L = 1;                        // 打开A相的低端
  114.                         ADC_CONTR = 0XEC;        // 选择P1.4作为ADC输入 即B相电压
  115.                         CMPCR1 = 0x9C;                //下降沿中断
  116.       break;
  117.    case 5: // CB
  118.                       PWM0_L=0;        PWM2_L=0;
  119.                         CCAP0H=0;        CCAP1H=0;        CCAP2H = PWM_Value;// 打开C相的高端
  120.                       PWM1_L = 1;                        // 打开B相的低端
  121.                         ADC_CONTR = 0XEB;        // 选择P1.3作为ADC输入 即a相电压
  122.                         CMPCR1 = 0xAC;                //上升沿中断
  123.          
  124.                 break;
  125.          
  126.         default:
  127.                 break;
  128.   }       
  129. }



  130. void PWM_Init(void)
  131. {
  132.         PWM0_L = 0;
  133.         PWM1_L = 0;
  134.         PWM2_L = 0;
  135.        
  136. #if        (MCU_PIN == 20)
  137.         P3n_push_pull(0x70);
  138. #endif
  139. #if        (MCU_PIN == 16)
  140.         P3n_push_pull(0x48);
  141.         P5n_push_pull(0x20);
  142. #endif

  143. //        CMOD = 1 << 1; //选择系统时钟/2为时钟源,即PWM频率=24M/2/256=46.9K
  144.         CMOD = 5 << 1; //选择系统时钟/4为时钟源,即PWM频率=24M/4/256=23.4K
  145. //        CMOD = 6 << 1; //选择系统时钟/6为时钟源,即PWM频率=24M/6/256=15.6K
  146.         CL=0;                        // PCA计数器清零
  147.         CH=0;
  148.        
  149.         PCA_PWM0 = 0X00;
  150.         CCAP0H=0;    // 初始化占空比为0% H的值装载到L中
  151.         CCAP0L=0;
  152.         CCAPM0=0x42;        // 设置为PWM模式
  153.        
  154.         PCA_PWM1 = 0X00;
  155.         CCAP1H=0;    // 初始化占空比为0%
  156.         CCAP1L=0;
  157.         CCAPM1=0x42;        // 设置为PWM模式
  158.        
  159.         PCA_PWM2 = 0X00;
  160.         CCAP2H=0;    // 初始化占空比为0%
  161.         CCAP2L=0;
  162.         CCAPM2=0x42;        // 设置为PWM模式
  163.        
  164.         CR = 1;
  165. }

  166. void ADC_Init(void)
  167. {
  168.         P1n_pure_input(0x38);
  169.         P1ASF = 0X38; // 开通P1.3 P1.4 P1.5的AD输入口
  170. }

  171. void CMP_INT(void) interrupt 21
  172. {
  173.         CMPCR1 &= ~0X40; // 需软件清除中断标志位
  174.         if(Step<5)        Step++;
  175.         else                Step = 0;
  176.         StepXL();
  177.         TimeOut = 10;        //10ms超时
  178. }

  179. void CMP_Init(void)
  180. {
  181.         CMPCR1 = 0X8C;        // 1000 1100 打开比较器,P5.4作为比较器的反相输入端,ADC引脚作为正输入端
  182.         CMPCR2 = 60;        // 60个时钟滤波
  183.         P5n_pure_input(0x10);
  184. }

  185. u8 StartMotor(void)
  186. {
  187.         u16 timer,i;
  188.         DISABLE_CMP_INT;        // 禁止比较器中断
  189.         PWM_Value = 30;                // 初始占空比=16/256=6%
  190.         Step = 0;
  191.         StepXL();                        // 初始位置
  192.         Delay_n_ms(5);//delay_ms(5);
  193.         timer = 300;

  194.         while(1)
  195.         {
  196.                 for(i=0; i<timer; i++)        delay_us(50);  //
  197.                 timer -= timer /15 + 1;
  198.                 if(timer < 25)        return(1);
  199.                 if( Step < 5)        Step++;
  200.                 else                        Step = 0;
  201.                 StepXL();
  202.         }
  203. }

  204. void T0_Iint(void)
  205. {
  206.         Timer0_AsTimer();        /* 时器0用做定时器        */
  207.         Timer0_12T();                /* Timer0 clodk = fo/12        12分频,        default        */
  208.         Timer0_16bit();
  209.         Timer0_Gate_INT0_P32();        /* 时器0由外部INT0高电平允许定时计数 */
  210.         TH0 = 0;
  211.         TL0 = 0;
  212.         TR0 = 1; // 打开定时器0
  213.         ET0 = 1;// 允许ET0中断
  214. }

  215. void T0_Interrupt(void) interrupt 1
  216. {
  217.         Rx_cnt = 0;                        //一旦出现溢出, 则开始的n个脉冲无效
  218.         RxPulseWide = 1000;        //停止
  219.         B_RxOk = 1;                        //虚拟收到一个脉冲
  220. }

  221. /********************* INT0中断函数 *************************/
  222. void INT0_int (void) interrupt INT0_VECTOR
  223. {
  224.         u16        j;
  225.        
  226.         TR0 = 0;
  227.         j = ((u16)TH0 << 8) + TL0;
  228.         TH0 = 0;
  229.         TL0 = 0;
  230.         TR0 = 1;

  231.         if(++Rx_cnt >= 5)        Rx_cnt = 5;
  232.         j >>= 1;        //为了好处理, 转成单位为us
  233.         if((j >= 800) && (j <= 2000) && (Rx_cnt == 5))
  234.         {
  235.                 RxPulseWide = j;
  236.                 B_RxOk = 1;                //标志收到一个脉冲
  237.         }

  238. }


  239. /**********************************************/
  240. void main(void)
  241. {
  242.         u16 j;

  243.         PWM_Init();
  244.         ADC_Init();
  245.         CMP_Init();
  246.         T0_Iint();

  247.         IE0 = 0;        // 清除外中断0标志位
  248.         EX0 = 1;        // INT0 Enable
  249.         IT0 = 1;        //INT0 下降沿中断
  250.        
  251.         RxPulseWide = 1000;
  252.         PWW_Set = 0;
  253.         cnt10ms = 0;
  254.         Rx_cnt  = 0;
  255.         TimeOut = 0;

  256.         EA  = 1; // 打开总中断
  257.        
  258.         while (1)
  259.         {
  260.                 Delay_n_ms(1);        //延时1ms, 主程序在此节拍下运行

  261.                 if(TimeOut > 0)
  262.                 {
  263.                         if(--TimeOut == 0)        //堵转超时
  264.                         {
  265.                                 CCAP0H=0;        CCAP1H=0;        CCAP2H=0;  // 占空比为0
  266.                                 PWM0_L=0;        PWM1_L=0;        PWM2_L=0;
  267.                                 DISABLE_CMP_INT; // 关比较器中断
  268.                                 Delay_n_ms(250);        //堵转时,延时1秒再启动
  269.                                 Delay_n_ms(250);
  270.                                 Delay_n_ms(250);
  271.                                 Delay_n_ms(250);

  272.                                 RxPulseWide = 1000;
  273.                                 PWW_Set   = 0;
  274.                                 PWM_Value = 0;
  275.                                 B_RxOk = 0;
  276.                                 B_RUN  = 0;
  277.                                 Rx_cnt = 0;
  278.                                 TimeOut = 0;
  279.                         }
  280.                 }
  281.                
  282.                 if(B_RxOk)        //收到一个脉冲
  283.                 {
  284.                         B_RxOk = 0;
  285.                         j = RxPulseWide;
  286.                         if(j >= 1100)                                // 1100~1610对应PWM占空比值0~255
  287.                         {
  288.                                 j = (j - 1100) >> 1;        //2us对应PWM一个步进
  289.                                 if(j > 256)        j = 255;
  290.                         }
  291.                         else        j = 0;
  292.                         PWW_Set = (u8)j;
  293.                 }
  294.                
  295.                 if(!B_RUN && (PWW_Set >= 30))                // PWM_Set >= 30, 并且马达未运行, 则启动马达
  296.                 {
  297.                         StartMotor();        // 启动马达
  298.                         CMPCR1 &= ~0X40; // 需软件清除中断标志位
  299.                         ENABLE_CMP_INT; // 打开比较器中断
  300.                         B_RUN = 1;
  301.                         TimeOut = 0;
  302.                 }
  303.                
  304.                
  305.                 if(++cnt10ms >= 10)                // 10ms时隙
  306.                 {
  307.                         cnt10ms = 0;
  308.                         if(B_RUN)
  309.                         {
  310.                                 if(PWM_Value < PWW_Set)        PWM_Value++;
  311.                                 if(PWM_Value > PWW_Set)        PWM_Value--;
  312.                                 if(PWM_Value < 20)        // 停转
  313.                                 {
  314.                                         PWM_Value = 0;
  315.                                         B_RUN = 0;
  316.                                         CCAP0H=0;        CCAP1H=0;        CCAP2H=0;  // 占空比为0
  317.                                         PWM0_L=0;        PWM1_L=0;        PWM2_L=0;
  318.                                         DISABLE_CMP_INT; // 关比较器中断
  319.                                 }
  320.                         }
  321.                 }
  322.        
  323.         }
  324. }



复制代码





STC15W401AS-实现四轴飞行器无刷电机的电调控制-参考程序和电路 (2).ZIP

161。85 KB, 下载次数: 0

地板
angmall 发表于 2019-9-14 07:37
你可以试试这个

DIY四轴飞行器如何入门?

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

本版积分规则

|手机版|小黑屋|单片机论坛 |51Hei单片机16群 联系QQ:125739409;技术交流QQ群7344883

Powered by 单片机教程网

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