单片机/MCU论坛
直播中

xymbmcu

12年用户 1025经验值
擅长:可编程逻辑
私信 关注
[文章]

四轴飞行器的设计之四轴主板的综合程序——STC15单片机实战指南连载

前面比较全面的讲述了四轴飞行器的硬件设计和软件中PID算法以及四元数与滤波算法,这节放出四轴主板的程序代码。  
例程比较复杂,这里采用了模块化编程的思路,按功能将其各个函数进行分类。笔者刚开始计划这部分的例程不贴到书上,但怕读者又说读者开源不够,与此,将完整的一套四轴源码贴到这里,做到真正的开源,起到让读者学习的目的。但读者需要注意的,该例程不像前面的小实例那样简单,读者再学习的时候,要静下心来,边读例程,边理解,同时一定要做记录,达到真正的理解。再者,便于读者调试,这里保留了笔者调试时所用的串口示波器源码,这样,可大大降低读者调试的难度,同时,所有“.c”文件对应的头文件“.h”文件,这里全部省略,里面主要是对变量和函数的声明,学到这里,对于函数的声明等,应该能熟练于心了。接下来,我们开始上菜,读者慢慢“享用”。
  1. /* =============         1        STC四轴正式版程序.c                 */
  2. #include "includes.h"
  3. #include "main.h"

  4. #define Check2401  1    //2401与mcu通信检测           置0屏蔽置1开启
  5. #define ReseveData 1    //飞行器接收数据控
  6. #define OutData    1                //飞行器内部数据输出

  7. void main()
  8. {
  9.     FlyAllInit();               //飞行器各模块初始化

  10. #if Check2401
  11.     Check24L01();                 //检测2401是否正常 不正常的话串口输出error
  12. #endif        
  13.     while(1)
  14.     {         
  15.       #if ReseveData
  16.               Reseve2401();        //接收2401数据
  17.       #endif                  
  18.               
  19.           #if  OutData
  20.           OutPutData();                //输出飞机内部调试数据
  21.           #endif                        
  22.    }         
  23. }
  24.         /* =============         2        filtering.c                 */
  25. #include
  26. #include
  27. #include
  28. #include
  29. #include
  30. #include
  31. #include <timer.h>
  32. #include
  33. #include
  34. #include
  35. #include "outputdata.h"
  36. #include "stdio.h"
  37. #include "filtering.h"

  38. /*-- 3-axis accelerometer data collected from MPU --*/
  39. short Z_angle,Y_angle,X_angle;
  40. /*-- Y-axis gyroscope     data collected from MPU --*/
  41. short Y_gyro,X_gyro,Z_gyro;
  42. /*- The final angular data filtered by Kalman Filter --*/
  43. short  X_gyroInit, Y_gyroInit, Z_gyroInit;

  44. /*------- Data collection -------*/
  45. void Read_MPU()
  46. {
  47.          
  48.         Z_angle = GetData(ACCEL_ZOUT_H);;
  49.         //Z_angle = (Z_angle/8192)*9.807;         //Z-axis accelerometer
  50.          
  51.         Y_angle = GetData(ACCEL_YOUT_H);
  52.         //Y_angle = (Y_angle/8192)*9.807;         //Y-axis accelerometer
  53.          
  54.         X_angle = GetData(ACCEL_XOUT_H);
  55.         //X_angle = (X_angle/8192)*9.807;
  56.     X_gyro=xgy();
  57.         Y_gyro=ygy();
  58.         Z_gyro=zgy();

  59. }

  60. static short xgy(void)
  61. {
  62.          
  63.         short i,j,k;
  64.         short tmp;
  65.    
  66.         X_gyro = GetData(GYRO_XOUT_H);;
  67.     X_gyro/= 16.4;         //X-axis accelerometer
  68.         i = X_gyro;

  69.         X_gyro = GetData(GYRO_XOUT_H);;
  70.     X_gyro/= 16.4;         //X-axis accelerometer
  71.         j = X_gyro;

  72.         X_gyro = GetData(GYRO_XOUT_H);
  73.     X_gyro/= 16.4;         //X-axis accelerometer
  74.         k = X_gyro;
  75.         if (i > j)
  76.         {
  77.                 tmp = i; i = j; j = tmp;
  78.         }
  79.         if (k > j)
  80.           tmp = j;
  81.         else if(k > i)
  82.           tmp = k;
  83.     else
  84.       tmp = i;
  85.         return tmp;
  86. }

  87. short ygy(void)
  88. {

  89.         short i,j,k;
  90.         short tmp;
  91.          
  92.         Y_gyro = GetData(GYRO_YOUT_H);
  93.         Y_gyro/= 16.4;                                                  //Y-axis gyroscope
  94.         i = Y_gyro;

  95.         Y_gyro =   GetData(GYRO_YOUT_H);
  96.         Y_gyro/= 16.4;                                                  //Y-axis gyroscope
  97.         j = Y_gyro;

  98.         Y_gyro =   GetData(GYRO_YOUT_H);;
  99.         Y_gyro/= 16.4;                                                  //Y-axis gyroscope
  100.         k = Y_gyro;
  101.         if (i > j)
  102.         {
  103.                 tmp = i; i = j; j = tmp;
  104.         }
  105.         if (k > j)
  106.           tmp = j;
  107.         else if(k > i)
  108.           tmp = k;
  109.     else
  110.       tmp = i;
  111.         return tmp;
  112. }

  113. short zgy(void)
  114. {

  115.         short i,j,k;
  116.         short tmp;

  117.         Z_gyro =  GetData(GYRO_ZOUT_H);;
  118.         Z_gyro/= 16.4;
  119.         i = Z_gyro;

  120.         Z_gyro =  GetData(GYRO_ZOUT_H);
  121.         Z_gyro/= 16.4;
  122.         j = Z_gyro;

  123.         Z_gyro =  GetData(GYRO_ZOUT_H);
  124.         Z_gyro/= 16.4;
  125.         k = Z_gyro;
  126.         if (i > j)
  127.         {
  128.                 tmp = i; i = j; j = tmp;
  129.         }
  130.         if (k > j)
  131.           tmp = j;
  132.         else if(k > i)
  133.           tmp = k;
  134.     else
  135.       tmp = i;
  136.         return tmp;
  137. }
  138. void Delay1ms()                //@30.000MHz
  139. {
  140.         unsigned char i, j;

  141.         i = 30;
  142.         j = 43;
  143.         do
  144.         {
  145.                 while (--j);
  146.         } while (--i);
  147. }
  148. void gyro_init(void)
  149. {
  150.         int i=0;
  151.         int x,y,z;
  152.         short a,b,c;
  153.         for(i=0;i<100;i++)
  154.         {        
  155.                 a=xgy() ;
  156.                 b=ygy() ;
  157.                 c=zgy() ;
  158.                 x=x+a;
  159.                 y=y+b;
  160.                 z=z+c;
  161.                 Delay1ms();
  162.         }
  163.     X_gyroInit=x/100;
  164.     Y_gyroInit=y/100;
  165.     Z_gyroInit=z/100;
  166. }
  167.         /* =============         3        control.c                 */
  168. #include
  169. #include
  170. #include
  171. #include
  172. #include
  173. #include
  174. #include
  175. #include
  176. #include
  177. #include
  178. #include "outputdata.h"
  179. #include "stdio.h"
  180. #include "filtering.h"
  181. #include "control.h"
  182. #include "includes.h"

  183. extern  unsigned char RXBUF[8];
  184. extern  float Pitch;   //x
  185. extern  float Roll;    //y
  186. extern  float Average_Gx,Average_Gy,Average_Gz  ;
  187. extern  int key;
  188. unsigned int Controldata_THROTTLE_Set=0;//1880-50-50-100+30;
  189. //************************************************
  190. int  Controldata_THROTTLE=0  ;         //??
  191. int  Controldata_PITCH   =0  ;         //??
  192. int  Controldata_ROLL    =0  ;         //??
  193. int  Controldata_YAW     =0  ;         //??
  194. int  Controldata_OFFSET  =0  ;         //??
  195. unsigned int   ControlNum=0  ;
  196. //************************************************   
  197. float  IUX=0.0,IUY=0.0;                              
  198. float  COUT_PITCHZ,COUT_PITCHF,COUT_ROLLZ,COUT_ROLLF;

  199. float PWM_XZ,PWM_XF,PWM_YZ,PWM_YF;//?????pwm?
  200. float Yaw1=0;

  201. //*************************************************
  202. void MainControl()
  203. {
  204.         Get_Control_Data() ;
  205.         Control();
  206. }
  207. //=============================================================
  208. float Controldata_ROLLleft=0,Controldata_ROLLright=0;
  209. float  Controldata_PITCHfront=0, Controldata_PITCHback=0;
  210. int error=0;
  211. extern int keyk;
  212. extern unsigned int s;
  213. int ss=0;

  214. void Get_Control_Data()
  215. {
  216.         float a=0,b=530,c=521,d=527;
  217.         if(keyk==1)
  218.         {
  219.                 d =    RXBUF[0]*16+RXBUF[1];         //oá1?
  220.                 b =    RXBUF[2]*16+RXBUF[3];         //????
  221.                 c =    RXBUF[4]*16+RXBUF[5];         //??o?
  222.                 a =    RXBUF[6]*16+RXBUF[7];         //óí??
  223.         //*********************脱控保护******************************        
  224.                 if(error==1)
  225.                 {
  226.                         if(ss==0)
  227.                         {ss=s;}
  228.                         a=a-(s-ss)*20;
  229.                 }         
  230.                 else
  231.                 ss=0;
  232.         }
  233.         //***********************************************************
  234.         if(a>1024)
  235.         {a=1024;}
  236.         a= a/1024.0 ;

  237.         if((b>=530&b<=540)||(b<=530&b>=520))
  238.         {b=530;}
  239.         b=b-530;
  240.         if(b>0)
  241.         {b=b/494.0;}
  242.         else
  243.         {b=b/530.0;}

  244.         if((c>=521&c<=531)||(c<=521&c>=511))
  245.         {c=521.0;}
  246.         c=c-521;
  247.         if(c>0)
  248.         {c=c/523.0;}
  249.         else
  250.         {c=c/521.0;}

  251.         if((d>=517&d<=527)||(d<=537&d>=527))
  252.         {d=527;}
  253.         d=d-527;
  254.         if(d>0)
  255.         {d=d/507.0;}
  256.         else
  257.         {d=d/527.0;}
  258.                                                                           
  259.         if(b>1)
  260.          b=1;
  261.         else if(b<-1)
  262.          b=-1;
  263.         //-------------
  264.         if(c>1)
  265.          c=1;
  266.         else if(c<-1)
  267.          c=-1;
  268.         //-------------
  269.         if(d>1)
  270.          d=1;
  271.         else if(d<-1)
  272.          d=-1;  
  273.         /*****************************/                                       
  274.         Controldata_THROTTLE=a*2400;
  275.         Controldata_PITCH=  b*20;
  276.         Controldata_YAW =   c*180;
  277.         Controldata_ROLL =  d*20;
  278.                
  279.         if( Controldata_PITCH>0)
  280.         {Controldata_PITCHfront=0 ,Controldata_PITCHback=         Controldata_PITCH;}
  281.         else
  282.         {Controldata_PITCHfront=Controldata_PITCH ,Controldata_PITCHb        ack= 0;}
  283.                  
  284.         if(Controldata_ROLL>0)
  285.         {
  286.                  Controldata_ROLLleft=0;
  287.                 Controldata_ROLLright=Controldata_ROLL;
  288.         }
  289.         else
  290.         {
  291.                 Controldata_ROLLleft=Controldata_ROLL;
  292.                 Controldata_ROLLright=0;
  293.         }
  294. }

  295. extern float IntegralZ;
  296. #define MINPWM 0
  297. #define MAXPWM 2699

  298. void Control(void)
  299. {
  300.         float  EX0=0.0,EX1=0.0,EY0=0.0,EY1=0.0;      
  301.         //-----------------------------  
  302.         float PID_P_Y , PID_D_Y ;//, PID_I_Y;
  303.         float PID_P_X , PID_D_X ;//, PID_I_X;
  304.         float PID_P_Z , PID_D_Z;
  305.         /***********************整定PID***************************/
  306.         EX0=Pitch;  
  307.         
  308.         EY0=Roll;
  309.         //********************************************************
  310.         PID_P_Y=3.2;//4;//4.0;//3.1;  
  311.         PID_D_Y=1.2;//0.4; 0.45; 0.43; 2.85; 0.6; 0.815+0.1; 0.86;

  312.         PID_P_X=3.2;//3.2;;//4;//3.0;//9.41;//15-1-1-0.4;
  313.         PID_D_X=1.2;//1.2;//1.2;//0.4;//0.4;//0.45;//0.6;//2.85;
  314.         //0.6;//2.515;//1.555+1+0.3+0.2;

  315.         PID_P_Z=0;//5;//0.2;
  316.         PID_D_Z=0;//0.03;
  317.         /**********************************************************/
  318.         Yaw1=PID_P_Z*(IntegralZ-Controldata_YAW)+PID_D_Z* Average_Gz;
  319.         if(Yaw1>300)
  320.         {Yaw1=300;}
  321.         else if(Yaw1<-300)
  322.         {Yaw1=-300;}
  323.         /*********************************************************/
  324. PWM_XF= (float)(Controldata_THROTTLE)- (EX0-
  325. Controldata_PITCHfront)*PID_P_X + (Average_Gy)*PID_D_X  -
  326. (EY0-Controldata_ROLLleft)*PID_P_Y-(Average_Gx)*PID_D_Y +Yaw1;
  327.     PWM_YF=(float)(Controldata_THROTTLE)-(EX0-
  328.         Controldata_PITCHfront)*PID_P_X + (Average_Gy)*PID_D_X  + (EY0-
  329.         Controldata_ROLLright)*PID_P_Y+(Average_Gx)*PID_D_Y -Yaw1;  
  330. PWM_XZ=(float)(Controldata_THROTTLE)+ (EX0-
  331. Controldata_PITCHback)*PID_P_X - (Average_Gy)*PID_D_X  - (EY0-
  332. Controldata_ROLLleft)*PID_P_Y-(Average_Gx)*PID_D_Y  -Yaw1;  
  333.         PWM_YZ=(float)(Controldata_THROTTLE)+ (EX0-
  334.         Controldata_PITCHback)*PID_P_X – (Average_Gy)*PID_D_X + (EY0-
  335.         Controldata_ROLLright)*PID_P_Y+(Average_Gx)*PID_D_Y +Yaw1;
  336.         //**********************************************************
  337.         #if 1         // 方便调试
  338.          if(Controldata_THROTTLE<30)
  339.          {
  340.                  PWM_XF=PWM_YF= PWM_XZ= PWM_YZ=0;
  341.                 IntegralZ=0;
  342.                 PWM(0,0,0,0) ;
  343.          }
  344.         #endif

  345.         if( PWM_XZ
  346.          PWM_XZ=MINPWM;
  347.         else if( PWM_XZ>MAXPWM)
  348.          PWM_XZ=MAXPWM;

  349.         if( PWM_XF
  350.          PWM_XF=MINPWM;
  351.         else if( PWM_XF>MAXPWM)
  352.          PWM_XF=MAXPWM;

  353.         if( PWM_YZ
  354.          PWM_YZ=MINPWM;
  355.         else if( PWM_YZ>MAXPWM)
  356.          PWM_YZ=MAXPWM;

  357.         if( PWM_YF
  358.          PWM_YF=MINPWM;
  359.         else if( PWM_YF>MAXPWM)
  360.          PWM_YF=MAXPWM;
  361.         /**********************************************/
  362.         PWM(PWM_XZ,PWM_XF,PWM_YF,PWM_YZ) ;
  363. }
  364.         /* =============         4        spi.c                 */
  365. #include "includes.h"
  366. #include "spi.h"
  367. #include
  368. typedef bit BOOL;
  369. typedef unsigned char BYTE;
  370. typedef unsigned short WORD;
  371. typedef unsigned long DWORD;

  372. #define FOSC            11059200L
  373. #define BAUD            (65536 - FOSC / 4 / 115200)

  374. #define null           0
  375. #define FALSE           0
  376. #define TRUE            1

  377. //sfr  AUXR           =   0x8e;      //辅助寄存器
  378. //sfr P_SW1           =   0xa2;      //外设功能切换寄存器1
  379. #define SPI_S0          0x04
  380. #define SPI_S1          0x08

  381. //sfr SPSTAT          =   0xcd;                   //SPI状态寄存器
  382. #define SPIF            0x80                    //SPSTAT.7
  383. #define WCOL            0x40                    //SPSTAT.6
  384. //sfr SPCTL           =   0xce;                   //SPI控制寄存器
  385. #define SSIG            0x80                    //SPCTL.7
  386. #define SPEN            0x40                    //SPCTL.6
  387. #define DORD            0x20                    //SPCTL.5
  388. #define MSTR            0x10                    //SPCTL.4
  389. #define CPOL            0x08                    //SPCTL.3
  390. #define CPHA            0x04                    //SPCTL.2
  391. #define SPDHH           0x00                    //CPU_CLK/4
  392. #define SPDH            0x01                    //CPU_CLK/16
  393. #define SPDL            0x02                    //CPU_CLK/64
  394. #define SPDLL           0x03                    //CPU_CLK/128
  395. //sfr SPDAT           =   0xcf;                   //SPI数据寄存器

  396. //***it SS             =   P2^4;                   //SPI的SS脚,连接到Flash的CE

  397. #define SFC_WREN        0x06                    //串行Flash命令集
  398. #define SFC_WRDI        0x04
  399. #define SFC_RDSR        0x05
  400. #define SFC_WRSR        0x01
  401. #define SFC_READ        0x03
  402. #define SFC_FASTREAD    0x0B
  403. #define SFC_RDID        0xAB
  404. #define SFC_PAGEPROG    0x02
  405. #define SFC_RDCR        0xA1
  406. #define SFC_WRCR        0xF1
  407. #define SFC_SECTORER    0xD7
  408. #define SFC_BLOCKER     0xD8
  409. #define SFC_CHIPER      0xC7

  410. void InitSpi();
  411. BYTE SpiShift(BYTE dat);

  412. void InitSpi()
  413. {
  414.   ACC = P_SW1;                                       //切换到第一组SPI
  415.   ACC &= ~(SPI_S0 | SPI_S1);           //SPI_S0=0 SPI_S1=0
  416.   P_SW1 = ACC;            //(P1.2/SS, P1.3/MOSI, P1.4/MISO, P1.5/SCLK)

  417.     SPSTAT = SPIF | WCOL;                 //清除SPI状态
  418.     SPCTL = SSIG | SPEN | MSTR;    //设置SPI为主模式
  419.         IE2&=0XFC;
  420. }

  421. /************************************************
  422. 使用SPI方式与Flash进行数据交换
  423. 入口参数:
  424.     dat : 准备写入的数据
  425. 出口参数:
  426.     从Flash中读出的数据
  427. ************************************************/
  428. BYTE SpiShift(BYTE dat)
  429. {
  430.     SPDAT = dat;                          // 触发SPI发送
  431.     while (!(SPSTAT & SPIF));          // 等待SPI数据传输完成
  432.     SPSTAT = SPIF | WCOL;                         // 清除SPI状态
  433.    
  434.     return SPDAT;
  435. }
  436.         /* =============         5        NRF24L01.c                 */
  437. #include
  438. #include "nrf24l01.h"
  439. #include "spi.h"

  440. const unsigned char TX_ADDRESS[TX_ADR_WIDTH]=
  441.                                                 {0x34,0x43,0x10,0x10,0x01};
  442. const unsigned char RX_ADDRESS[RX_ADR_WIDTH]=
  443.                                                 {0x34,0x43,0x10,0x10,0x01};

  444. void NRF24L01_Init(void)
  445. {
  446.     InitSpi();
  447.         NRF24L01_CE=0;
  448.         NRF24L01_CSN=1;        
  449. }

  450. unsigned char NRF24L01_Check(void)
  451. {
  452.     unsigned char buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
  453.         unsigned char i;
  454.          
  455.         NRF24L01_Write_Buf(WRITE_REG1+TX_ADDR,buf,5);         
  456.         NRF24L01_Read_Buf(TX_ADDR,buf,5);   
  457.         for(i=0;i<5;i++) if(buf[i]!=0XA5) break;                                                                    
  458.         if(i!=5) return 1;
  459.         return 0;                 
  460. }                  

  461. unsigned char  NRF24L01_Write_Reg(unsigned char  reg,unsigned char  value)
  462. {
  463.         unsigned char  status;        
  464.            NRF24L01_CSN=0;
  465.           status =SpiShift(reg);
  466.           SpiShift(value);
  467.           NRF24L01_CSN=1;  
  468.           return(status);               
  469. }

  470. unsigned char NRF24L01_Read_Reg(unsigned char reg)
  471. {
  472.         unsigned char  reg_val;            
  473.          NRF24L01_CSN = 0;
  474.           SpiShift(reg);
  475.           reg_val=SpiShift(0XFF);
  476.           NRF24L01_CSN = 1;                    
  477.           return(reg_val);
  478. }        

  479. unsigned char NRF24L01_Read_Buf(unsigned char  reg,unsigned char  *pBuf,unsigned char  len)
  480. {
  481.         unsigned char  status,u8_ctr;               
  482.           NRF24L01_CSN = 0;
  483.           status=SpiShift(reg);           
  484.          for(u8_ctr=0;u8_ctr
  485.           NRF24L01_CSN=1;
  486.           return status;
  487. }

  488. unsigned char  NRF24L01_Write_Buf(unsigned char  reg, unsigned char  *pBuf, unsigned char  len)
  489. {
  490.         unsigned char  status,u8_ctr;            
  491.          NRF24L01_CSN = 0;
  492.           status = SpiShift(reg);
  493.           for(  u8_ctr=0; u8_ctr
  494.           NRF24L01_CSN = 1;
  495.           return status;
  496. }                                   

  497. unsigned char  NRF24L01_TxPacket(unsigned char  *txbuf)
  498. {
  499.         unsigned char  sta;
  500.    
  501.         NRF24L01_CE=0;
  502.           NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);
  503.          NRF24L01_CE=1;
  504.         while(NRF24L01_IRQ!=0);
  505.         sta=NRF24L01_Read_Reg(STATUS);           
  506.         NRF24L01_Write_Reg(WRITE_REG1+STATUS,sta);
  507.         if(sta&MAX_TX)
  508.         {
  509.                 NRF24L01_Write_Reg(FLUSH_TX,0xff);
  510.                 return MAX_TX;
  511.         }
  512.         if(sta&TX_OK)
  513.         {
  514.                 return TX_OK;
  515.         }
  516.         return 0xff;
  517. }

  518. unsigned char  NRF24L01_RxPacket(unsigned char  *rxbuf)
  519. {
  520.         unsigned char  sta;                                                                              
  521.   
  522.         sta=NRF24L01_Read_Reg(STATUS);            
  523.         NRF24L01_Write_Reg(WRITE_REG1+STATUS,sta);
  524.         if(sta&RX_OK)
  525.         {
  526.                 NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);
  527.                 NRF24L01_Write_Reg(FLUSH_RX,0xff);
  528.                 return 0;
  529.         }           
  530.         return 1;
  531. }                                            
  532.            
  533. void RX_Mode(void)
  534. {
  535.         NRF24L01_CE=0;         
  536.           NRF24L01_Write_Buf(WRITE_REG1+RX_ADDR_P0,(unsigned         char*)RX_ADDRESS,RX_ADR_WIDTH);
  537.          
  538.           NRF24L01_Write_Reg(WRITE_REG1+EN_AA,0x01);   
  539.           NRF24L01_Write_Reg(WRITE_REG1+EN_RXADDR,0x01);
  540.           NRF24L01_Write_Reg(WRITE_REG1+RF_CH,40);                  
  541.           NRF24L01_Write_Reg(WRITE_REG1+RX_PW_P0,RX_PLOAD_WIDTH);   
  542.           NRF24L01_Write_Reg(WRITE_REG1+RF_SETUP,0x0f);  
  543.           NRF24L01_Write_Reg(WRITE_REG1+CONFIG1, 0x0f);
  544.           NRF24L01_CE = 1;
  545. }                                                
  546.          
  547. void TX_Mode(void)
  548. {                                                                                                                 
  549.         NRF24L01_CE=0;            
  550.           NRF24L01_Write_Buf(WRITE_REG1+TX_ADDR,(unsigned         char*)TX_ADDRESS,TX_ADR_WIDTH);
  551.           NRF24L01_Write_Buf(WRITE_REG1+RX_ADDR_P0,(unsigned         char*)RX_ADDRESS,RX_ADR_WIDTH);         

  552.           NRF24L01_Write_Reg(WRITE_REG1+EN_AA,0x01);
  553.           NRF24L01_Write_Reg(WRITE_REG1+EN_RXADDR,0x01);
  554.           NRF24L01_Write_Reg(WRITE_REG1+SETUP_RETR,0x1a);
  555.           NRF24L01_Write_Reg(WRITE_REG1+RF_CH,40);
  556.           NRF24L01_Write_Reg(WRITE_REG1+RF_SETUP,0x0f);
  557.           NRF24L01_Write_Reg(WRITE_REG1+CONFIG1,0x0e);
  558.         NRF24L01_CE=1;
  559. }                  
  560.         /* =============         6        AllInit.c                 */
  561. #include "includes.h"
  562. #include "AllInit.h"
  563. #include "main.h"

  564. #define RemoteControlData 0                //串口输出遥控器发送数值使能
  565. #define AttitudeData      1                        //串口输出姿态值使能
  566. #define RollData          1                        //输出y轴姿态
  567. #define PitchData         0                        //输出x轴姿态

  568. unsigned char RXBUF[33]={0,0,0,0,0,0,0,0};          //2401数据存储区
  569. int keyk=0;
  570. int ee=0;

  571. /************************************************
  572. 函数功能:检测2401与单片机通信是否正常
  573. *************************************************/
  574. void Check24L01()
  575. {
  576.     while( NRF24L01_Check())
  577.         {   
  578.                 printf("24l01 is error,please replacement 24l01 module! n");
  579.                 delayms__(100);
  580.         }
  581.         printf ("24l01 is ok!n");
  582. }
  583. /************************************************
  584. 函数功能:初始化飞行器各个模块
  585. *************************************************/
  586. void FlyAllInit()
  587. {
  588.    delayms_(100);
  589.    InitMPU6050();                              //初始化MPU-6050
  590.    Usart_Init();                  //初始化串口
  591.    PWMGO();                               //初始化PWM
  592.    NRF24L01_Init();                        //初始化2401
  593.    RX_Mode();                                        //设为接收模式
  594.    Time0_Init();             //初始化定时器
  595.    printf ("All module is ok!n Get ready to fly!n");
  596. }
  597. /************************************************
  598. 函数功能:飞行器接收2401数据
  599. *************************************************/
  600. void Reseve2401(void)
  601. {
  602.         if(NRF24L01_RxPacket(RXBUF)==0)        
  603.         {
  604.                 if((RXBUF[6]*16+RXBUF[7])<30)
  605.                 {keyk=1;}
  606.                 ee=0;error=0;
  607.                 RXBUF[32]=0;
  608.         }
  609.         else
  610.         {  
  611.                 if(keyk==1)
  612.                 ee++;
  613.         }
  614.         if(ee>=200)
  615.         {error=1;}
  616. }

  617. /************************************************
  618. 函数功能:飞行器输出内部数据
  619. *************************************************/
  620. void OutPutData()
  621. {
  622. //遥控器数值输出
  623. #if RemoteControlData
  624.         OutData[0]=    RXBUF[0]*16+RXBUF[1];  //横滚        
  625.         OutData[1]=    RXBUF[2]*16+RXBUF[3];  //俯仰        
  626.         OutData[2]=    RXBUF[4]*16+RXBUF[5];  //偏航        
  627.         OutData[3]=    RXBUF[6]*16+RXBUF[7];  //油门      
  628.         OutPut_Data();        
  629. #endif                                         
  630. //姿态输出
  631. #if AttitudeData
  632.         #if        PitchData
  633.                 OutData[0] = Pitch;
  634.                 OutData[1] = X_angle;
  635.                 OutData[2] = Average_Gy;
  636.                 // OutData[3] = A_angle_Y;;
  637.                 OutPut_Data();
  638.         #endif
  639.         #if RollData
  640.                 OutData[0] = Roll;
  641.                 OutData[1] = Y_angle;
  642.                 OutData[2] = Average_Gx;
  643.                 // OutData[3] = A_angle_Y;;
  644.                 OutPut_Data();
  645.         #endif  
  646. #endif  
  647. }
  648. /************************************************
  649. 函数名称:MotorTest()
  650. 函数功能:飞行器电机测试
  651. *************************************************/
  652. void MotorTest(void)
  653. {
  654.         //数值设定 0~2700;同时要屏蔽IMU.c 中断里面的MainControl
  655.         PWM(0,0,0,0);
  656. }

  657. void Delay100us()                //@30.000MHz
  658. {
  659.         unsigned char i, j;

  660.         i = 3;
  661.         j = 232;
  662.         do
  663.         {
  664.                 while (--j);
  665.         } while (--i);
  666. }

  667. void delayms__(int ms)
  668. {
  669.   int x,y;
  670.   for(x=ms;x>0;x--)
  671.   {
  672.    for(y=1000;y>0;y--)
  673.     ;
  674.   }
  675. }
  676. /* =============         7        MPU-6050.c                 */
  677. #include
  678. #include
  679. #include
  680. #include
  681. #define  uchar        unsigned char
  682. ***it    SCL=P3^4;                        //IIC时钟引脚定义    Rev8.0硬件
  683. ***it    SDA=P3^5;                        //IIC数据引脚定义
  684. void  InitMPU6050();                                                                                //初始化MPU6050
  685. void  Delay2us();
  686. void  I2C_Start();
  687. void  I2C_Stop();

  688. bit   I2C_RecvACK();

  689. void  I2C_SendByte(unsigned char dat);
  690. uchar I2C_RecvByte();

  691. void  I2C_ReadPage();
  692. void  I2C_WritePage();
  693. uchar Single_ReadI2C(uchar REG_Address);        //读取I2C数据
  694. void  Single_WriteI2C(uchar REG_Address,uchar REG_data);        
  695. //向I2C写入数据
  696. //I^C时序中延时设置,具体参见各芯片的数据手册  6050推荐最小1.3us 但是会出问题,这里延时实际1.9us左右
  697. void Delay2us()                //@27.000MHz
  698. {
  699.         unsigned char i;

  700.         i = 11;
  701.         while (--i);
  702. }
  703. //**************************************
  704. //I2C起始信号
  705. //**************************************
  706. void I2C_Start()
  707. {
  708.     SDA = 1;                    //拉高数据线
  709.     SCL = 1;                    //拉高时钟线
  710.     Delay2us();                 //延时
  711.     SDA = 0;                    //产生下降沿
  712.     Delay2us();                 //延时
  713.     SCL = 0;                    //拉低时钟线
  714. }
  715. //**************************************
  716. //I2C停止信号
  717. //**************************************
  718. void I2C_Stop()
  719. {
  720.     SDA = 0;                    //拉低数据线
  721.     SCL = 1;                    //拉高时钟线
  722.     Delay2us();                 //延时
  723.     SDA = 1;                    //产生上升沿
  724.     Delay2us();                 //延时
  725. }
  726. //**************************************
  727. //I2C接收应答信号
  728. //**************************************
  729. bit I2C_RecvACK()
  730. {
  731.     SCL = 1;                    //拉高时钟线
  732.     Delay2us();                 //延时
  733.     CY = SDA;                   //读应答信号
  734.     SCL = 0;                    //拉低时钟线
  735.     Delay2us();                 //延时
  736.     return CY;
  737. }
  738. //**************************************
  739. //向I2C总线发送一个字节数据
  740. //**************************************
  741. void I2C_SendByte(uchar dat)
  742. {
  743.     uchar i;
  744.     for (i=0; i<8; i++)         //8位计数器
  745.     {
  746.         dat <<= 1;              //移出数据的最高位
  747.         SDA = CY;               //送数据口
  748.         SCL = 1;                //拉高时钟线
  749.         Delay2us();             //延时
  750.         SCL = 0;                //拉低时钟线
  751.         Delay2us();             //延时
  752.     }
  753.     I2C_RecvACK();
  754. }
  755. //**************************************
  756. //从I2C总线接收一个字节数据
  757. //**************************************
  758. uchar I2C_RecvByte()
  759. {
  760.     uchar i;
  761.     uchar dat = 0;
  762.     SDA = 1;                    //使能内部上拉,准备读取数据,
  763.     for (i=0; i<8; i++)         //8位计数器
  764.     {
  765.         dat <<= 1;
  766.         SCL = 1;                //拉高时钟线
  767.         Delay2us();             //延时
  768.         dat |= SDA;             //读数据
  769.         SCL = 0;                //拉低时钟线
  770.         Delay2us();             //延时
  771.     }
  772.     return dat;
  773. }
  774. //**************************************
  775. //向I2C设备写入一个字节数据
  776. //**************************************
  777. void Single_WriteI2C(uchar REG_Address,uchar REG_data)
  778. {
  779.     I2C_Start();                  //起始信号
  780.     I2C_SendByte(SlaveAddress);   //发送设备地址+写信号
  781.     I2C_SendByte(REG_Address);    //内部寄存器地址,
  782.     I2C_SendByte(REG_data);       //内部寄存器数据,
  783.     I2C_Stop();                   //发送停止信号
  784. }
  785. //**************************************
  786. //从I2C设备读取一个字节数据
  787. //**************************************
  788. uchar Single_ReadI2C(uchar REG_Address)
  789. {
  790.         uchar REG_data;
  791.         I2C_Start();                   //起始信号
  792.         I2C_SendByte(SlaveAddress);    //发送设备地址+写信号
  793.         I2C_SendByte(REG_Address);     //发送存储单元地址,从0开始
  794.         I2C_Start();                   //起始信号
  795.         I2C_SendByte(SlaveAddress+1);  //发送设备地址+读信号
  796.         REG_data=I2C_RecvByte();       //读出寄存器数据
  797.         
  798.         SDA = 1;                    //写应答信号
  799.         SCL = 1;                    //拉高时钟线
  800.         Delay2us();                 //延时
  801.         SCL = 0;                    //拉低时钟线
  802.         Delay2us();                 //延时
  803.         
  804.         I2C_Stop();                    //停止信号
  805.         return REG_data;
  806. }

  807. //**************************************
  808. //初始化MPU6050
  809. //**************************************
  810. void InitMPU6050()
  811. {
  812.         Single_WriteI2C(PWR_MGMT_1, 0x00);        //解除休眠状态
  813.         Single_WriteI2C(SMPLRT_DIV, 0x07);  //陀螺仪125hz
  814.         Single_WriteI2C(CONFIG, 0x06);      //21HZ滤波 延时A8.5ms G8.3ms  
  815.         //此处取值应相当注意,延时与系统周期相近为宜
  816.         Single_WriteI2C(GYRO_CONFIG, 0x18); //陀螺仪500度/S 65.5LSB/g
  817.         Single_WriteI2C(ACCEL_CONFIG, 0x01);//加速度+-4g  8192LSB/g
  818. }
  819. //**************************************
  820. //合成数据
  821. //**************************************
  822. int GetData(uchar REG_Address)
  823. {
  824.         char H,L;
  825.         H=Single_ReadI2C(REG_Address);
  826.         L=Single_ReadI2C(REG_Address+1);
  827.         return (H<<8)+L;   //合成数据
  828. }
  829. /* =============         8        IMU.c                 */
  830. #include
  831. #include "includes.h"
  832. #include "IMU.H"
  833. #include "math.H"
  834.                            
  835. //#define Kp  28.1f   //10.1f
  836. //#define Ki   0.001f//0.011f                        
  837. //#define halfT 0.0020f   
  838. #define Kp   15.1f  //10.1f                        
  839. #define Ki   0.001        //0.001f//0.011f                        
  840. #define halfT 0.001        //0.0019f     
  841. float idata q0=1,q1=0,q2=0,q3=0;   
  842. float idata exInt=0,eyInt=0,ezInt=0;  
  843. float         Pitch ,        Roll;
  844. float a,b,c;
  845. float IntegralZ;
  846. /*********************************/
  847. #define KALMAN_Qy        0.015
  848. #define KALMAN_Ry        10.0000
  849. #define KALMAN_Qx        0.015
  850. #define KALMAN_Rx       10.0000
  851. #define KALMAN_Qz        0.015
  852. #define KALMAN_Rz        10.0000

  853. static double KalmanFilter_x(const double ResrcData,double ProcessNiose_Q,double MeasureNoise_R)
  854. {
  855.         double R = MeasureNoise_R;
  856.            double Q = ProcessNiose_Q;
  857.            static double x_last;
  858.            double x_mid = x_last;
  859.            double x_now;
  860.            static double p_last;
  861.            double p_mid ;
  862.            double p_now;
  863.            double kg;        

  864.            x_mid=x_last;                 //x_last=x(k-1|k-1),x_mid=x(k|k-1)
  865.            p_mid=p_last+Q;                 //p_mid=p(k|k-1),p_last=p(k-1|k-1),
  866.            kg=p_mid/(p_mid+R);
  867.            x_now=x_mid+kg*(ResrcData-x_mid);
  868.                
  869.            p_now=(1-kg)*p_mid;   
  870.            p_last = p_now;
  871.            x_last = x_now;
  872.            return x_now;               
  873. }
  874. static double KalmanFilter_y(const double ResrcData,double ProcessNiose_Q,double MeasureNoise_R)
  875. {
  876.            double R = MeasureNoise_R;
  877.            double Q = ProcessNiose_Q;
  878.            static double y_last;
  879.            double y_mid = y_last;
  880.            double y_now;
  881.            static double p_last;
  882.            double p_mid ;
  883.            double p_now;
  884.            double kg;        

  885.            y_mid=y_last;                 //x_last=x(k-1|k-1),x_mid=x(k|k-1)
  886.            p_mid=p_last+Q;                 //p_mid=p(k|k-1),p_last=p(k-1|k-1),Q=??éù
  887.            kg=p_mid/(p_mid+R);
  888.            y_now=y_mid+kg*(ResrcData-y_mid);
  889.                
  890.            p_now=(1-kg)*p_mid;   
  891.            p_last = p_now;
  892.            y_last = y_now;
  893.            return y_now;               
  894. }
  895. static double KalmanFilter_z(const double ResrcData,double ProcessNiose_Q,double MeasureNoise_R)
  896. {
  897.            double R = MeasureNoise_R;
  898.            double Q = ProcessNiose_Q;
  899.            static double z_last;
  900.            double z_mid = z_last;
  901.            double z_now;
  902.            static double p_last;
  903.            double p_mid ;
  904.            double p_now;
  905.            double kg;        

  906.            z_mid=z_last;                 //x_last=x(k-1|k-1),x_mid=x(k|k-1)
  907.            p_mid=p_last+Q;
  908.            kg=p_mid/(p_mid+R);
  909.            z_now=z_mid+kg*(ResrcData-z_mid);
  910.                
  911.            p_now=(1-kg)*p_mid;   
  912.            p_last = p_now;
  913.            z_last = z_now;
  914.            return z_now;               
  915. }

  916. void IMUupdate(float gx, float gy, float gz, float ax, float ay, float az)
  917. {
  918.          float norm;
  919.         //  float hx, hy, hz, bx, bz;
  920.           float vx, vy, vz;// wx, wy, wz;
  921.           float ex, ey, ez;

  922.           float q0q0 = q0*q0;
  923.           float q0q1 = q0*q1;
  924.           float q0q2 = q0*q2;
  925.          // float q0q3 = q0*q3;
  926.           float q1q1 = q1*q1;
  927.          // float q1q2 = q1*q2;
  928.           float q1q3 = q1*q3;
  929.           float q2q2 = q2*q2;
  930.           float q2q3 = q2*q3;
  931.           float q3q3 = q3*q3;
  932.         

  933.           norm = sqrt(ax*ax + ay*ay + az*az);
  934.           ax = ax /norm;
  935.           ay = ay / norm;
  936.           az = az / norm;
  937.            
  938.           vx = 2*(q1q3 - q0q2);
  939.           vy = 2*(q0q1 + q2q3);
  940.           vz = q0q0 - q1q1 - q2q2 + q3q3 ;

  941.           ex = (ay*vz - az*vy) ;
  942.           ey = (az*vx - ax*vz) ;
  943.           ez = (ax*vy - ay*vx) ;

  944.           exInt = exInt + ex * Ki;
  945.           eyInt = eyInt + ey * Ki;
  946.           ezInt = ezInt + ez * Ki;

  947.           gx = gx + Kp*ex + exInt;
  948.           gy = gy + Kp*ey + eyInt;
  949.           gz = gz + Kp*ez + ezInt;
  950.         
  951.                                           
  952.           q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;
  953.           q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT;
  954.           q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT;
  955.           q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT;

  956.           norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
  957.           q0 = q0 / norm;
  958.           q1 = q1 / norm;
  959.           q2 = q2 / norm;
  960.           q3 = q3 / norm;

  961.           b = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch
  962.           c = atan2(2 * q2 * q3 + 2 * q0 * q1, q0 * q0 - q1 * q1 - q2 * q2         + q3 * q3)* 57.3; // roll
  963.           //d = atan2(2 * q1 * q2+2 * q0 * q3,q0 * q0+q1 * q1-q2 * q2-q3         * q3)*57.3;

  964.         Pitch =b;
  965.         Roll = c;

  966. }
  967. /************************************************************/
  968. extern   short Y_gyro,X_gyro,Z_gyro;
  969. extern   short Z_angle,Y_angle,X_angle;
  970. extern  short  X_gyroInit, Y_gyroInit, Z_gyroInit;
  971. float         Average_Gx,Average_Gy,Average_Gz,Average_Ax,Average_Ay,
  972.                 Average_Az=0;
  973. float Average_Ax_old[4],Average_Ay_old[4],Average_Az_old[4];
  974. float A_angle_X,A_angle_Y,A_angle_Z;
  975. /*------- Data processing -------*/
  976. void MPU_pro()
  977. {
  978.         Average_Gx=X_gyro;//+15;//- X_gyroInit;
  979.         Average_Gy=Y_gyro;//+15;//- Y_gyroInit;
  980.         Average_Gz=Z_gyro;//- Z_gyroInit;
  981.         
  982.         Average_Ax=X_angle;
  983.         Average_Ay=Y_angle;
  984.     Average_Az=Z_angle;

  985.         Average_Ax_old[2]=Average_Ax_old[1];
  986.         Average_Ay_old[2]=Average_Ay_old[1];
  987.         Average_Az_old[2]=Average_Az_old[1];
  988.         Average_Ax_old[1]=Average_Ax_old[0];
  989.         Average_Ay_old[1]=Average_Ay_old[0];
  990.         Average_Az_old[1]=Average_Az_old[0];
  991.         Average_Ax_old[0]=Average_Ax;
  992.         Average_Ay_old[0]=Average_Ay;
  993.         Average_Az_old[0]=Average_Az;
  994. //**************************************************        
  995.          if(Average_Ay_old[2]!=0)
  996.          {
  997.                  IntegralZ+= Average_Gz        *0.01;
  998.                  if( IntegralZ>=359)
  999.                   IntegralZ=0;
  1000.                   if( IntegralZ<=-359)
  1001.                    IntegralZ=0;
  1002.          
  1003.                 Average_Ax=MidFilter( Average_Ax_old[0],Average_Ax_old[1],                 Average_Ax_old[2]);  
  1004.                 Average_Ay=MidFilter( Average_Ay_old[0],Average_Ay_old[1],                 Average_Ay_old[2]);  
  1005.             Average_Az=MidFilter( Average_Az_old[0],Average_Az_old[1],                 Average_Az_old[2]);   
  1006.         
  1007.                 A_angle_X=atan((float)(Average_Ax/sqrt(Average_Ay*
  1008.                 Average_Ay+Average_Az*Average_Az)))*57.3;
  1009.                 A_angle_Y =atan((float)(Average_Ay/sqrt(Average_Ax*
  1010.                 Average_Ax+Average_Az*Average_Az)))*57.3;
  1011.                 A_angle_Z =atan((float)(Average_Az/sqrt(Average_Ax*
  1012.                 Average_Ax+Average_Ay*Average_Ay)))*57.3;
  1013.                 //IMUupdate( Average_Gx*0.05044,Average_Gy*-0.05044,
  1014.                 //Average_Gz*0.03744,-Average_Ax,Average_Ay, Average_Az);
  1015.             IMUupdate( Average_Gx*0.05544,Average_Gy*-0.05544,
  1016.                 Average_Gz*0.05544,-Average_Ax,Average_Ay, Average_Az);
  1017.         }
  1018. }

  1019. float MidFilter(float a,float b,float c)
  1020. {

  1021.         float i,j,k;
  1022.         float tmp;
  1023.          
  1024.         i = a;
  1025.         j = b;
  1026.         k = c;
  1027.         if (i > j)
  1028.         {
  1029.                 tmp = i; i = j; j = tmp;
  1030.         }
  1031.         if (k > j)
  1032.           tmp = j;
  1033.         else if(k > i)
  1034.           tmp = k;
  1035.     else
  1036.       tmp = i;
  1037.         return tmp;
  1038. }
  1039. extern int  Controldata_THROTTLE  ;
  1040. int mmms=0;
  1041. int s=0;

  1042. void Angle_Calculate() interrupt 1
  1043. {         
  1044.       Read_MPU();          // 读取mpu6050数据
  1045.       MPU_pro();                   // 进行imu数据转换
  1046.       MainControl();             // 进行姿态控制
  1047. }
  1048.         /* =============         9        USART.c                 */
  1049. #include
  1050. #include
  1051. #include    
  1052. bit busy;
  1053. void Usart_Init()  //30m 波特率9600
  1054. {               
  1055.          SCON = 0x50;                //8位数据,可变波特率
  1056.     AUXR |= 0x40;                //定时器1时钟为Fosc,即1T
  1057.         AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  1058.         TMOD &= 0x0F;                //设定定时器1为16位自动重装方式
  1059.         TL1 = 0x41;                        //设定定时初值
  1060.         TH1 = 0xFD;                        //设定定时初值
  1061.         ET1 = 0;                        //禁止定时器1中断
  1062.         TR1 = 1;                        //启动定时器1
  1063.         REN=1;
  1064.         ES=1;
  1065.         EA=1;
  1066.         TI=1;
  1067. }
  1068. void Uart() interrupt 4 using 1
  1069. {
  1070.     if (RI)
  1071.     {
  1072.         RI = 0;                       
  1073.     }
  1074.     if (TI)
  1075.     {
  1076.         TI = 0;               
  1077.         busy = 0;            
  1078.     }
  1079. }
  1080. void SendData(unsigned char dat)
  1081. {
  1082.         SBUF = dat;
  1083.         while(!TI);
  1084.           TI = 0;      
  1085. }
  1086. void Send(int Ax,int Ay,int Az,int Gx,int Gy,int Gz)
  1087. {
  1088.         unsigned char sum=0;
  1089.         ES = 1;                          //打开串口中断
  1090.         SendData(0xAA);           //帧头
  1091.         SendData(0xAA);           //帧头
  1092.         SendData(0x02);           //功能字
  1093.         SendData(12);             //发送的数据长度
  1094.         SendData(Ax);             //低8位
  1095.         SendData(Ax>>8);          //高8位
  1096.         SendData(Ay);
  1097.         SendData(Ay>>8);
  1098.         SendData(Az);
  1099.         SendData(Az>>8);
  1100.         SendData(Gx);
  1101.         SendData(Gx>>8);
  1102.         SendData(Gy);
  1103.         SendData(Gy>>8);
  1104.         SendData(Gz);
  1105.         SendData(Gz>>8);
  1106.         sum+=0xAA;sum+=0xAA;sum+=0x02;sum+=12;
  1107.         sum+=Ax>>8;sum+=Ax;sum+=Ay>>8;sum+=Ay;sum+=Az>>8;sum+=Az;
  1108.         sum+=Gx>>8;sum+=Gx;sum+=Gy>>8;sum+=Gy;sum+=Gz>>8;sum+=Gz;
  1109.         SendData(sum);          //校验和
  1110.         ES = 0;                           //关闭串口中断
  1111. }
  1112.         /* =============         10        outputdata.c                 */
  1113. #include "outputdata.h"
  1114. #include "USART.h"

  1115. float OutData[4] = { 0 };

  1116. unsigned short CRC_CHECK(unsigned char *Buf, unsigned char CRC_CNT)
  1117. {
  1118.     unsigned short CRC_Temp;
  1119.     unsigned char i,j;
  1120.     CRC_Temp = 0xffff;

  1121.     for (i=0;i
  1122.         CRC_Temp ^= Buf[i];
  1123.         for (j=0;j<8;j++) {
  1124.             if (CRC_Temp & 0x01)
  1125.                 CRC_Temp = (CRC_Temp >>1 ) ^ 0xa001;
  1126.             else
  1127.                 CRC_Temp = CRC_Temp >> 1;
  1128.         }
  1129.     }
  1130.         return(CRC_Temp);
  1131. }

  1132. void OutPut_Data(void)
  1133. {
  1134.           int temp[4] = {0};
  1135.           unsigned int temp1[4] = {0};
  1136.           unsigned char databuf[10] = {0};
  1137.           unsigned char i;
  1138.           unsigned short CRC16 = 0;
  1139.           for(i=0;i<4;i++)
  1140.            {
  1141.             temp[i]  = (int)OutData[i];
  1142.             temp1[i] = (unsigned int)temp[i];
  1143.            }
  1144.    
  1145.           for(i=0;i<4;i++)
  1146.           {
  1147.             databuf[i*2]   = (unsigned char)(temp1[i]%256);
  1148.             databuf[i*2+1] = (unsigned char)(temp1[i]/256);
  1149.           }
  1150.   
  1151.           CRC16 = CRC_CHECK(databuf,8);
  1152.           databuf[8] = CRC16%256;
  1153.           databuf[9] = CRC16/256;
  1154.   
  1155.           for(i=0;i<10;i++)
  1156.                    SendData(databuf[i]);
  1157. }
  1158. /***************************************************************
  1159. * 功    能:串口示波器放数据用
  1160. ***************************************************************/
  1161. void uart_putstr(char ch[])
  1162. {
  1163.           unsigned char ptr=0;
  1164.           while(ch[ptr]){
  1165.     SendData((char)ch[ptr++]);
  1166. }
  1167. }
  1168.         /* =============         11        Timer.c                 */
  1169. #include
  1170. #include
  1171. void Time0_Init()                //10ms@27MHz 定时器0 16位12T自动重载
  1172. {
  1173.         AUXR &= 0x7F;                //定时器时钟12T模式
  1174.         TMOD &= 0xF0;                //设置定时器模式
  1175.     TL0 = 0x1C;                //设置定时初值
  1176.         TH0 = 0xA8;                //设置定时初值
  1177.         TF0 = 0;                        //清除TF0标志
  1178.         TR0 = 1;                        //定时器0开始计时
  1179.     IE=0X82        ;
  1180.         EA=1;
  1181. }

  1182. void Timer1Init(void)
  1183. {
  1184.         //        AUXR |= 0x40;
  1185.         TMOD &= 0x0F;
  1186.         IE  = 0x8a;
  1187.         TL1 = 0x54;
  1188.         TH1 = 0xF2;
  1189.         TF1 = 0;
  1190.         TR1 = 1;
  1191. }
  1192.         /* =============         12        STC15W4KPWM.c                 */
  1193. #include
  1194. #include
  1195. #include
  1196. #include
  1197. extern unsigned char RxBuf[20];
  1198. void PWMGO()
  1199. {
  1200.         //所有I/O口全设为准双向,弱上拉模式
  1201.         P0M0=0x00;P0M1=0x00;
  1202.         P1M0=0x00;P1M1=0x00;
  1203.         P2M0=0x00;P2M1=0x00;
  1204.         P3M0=0x00;P3M1=0x00;
  1205.         P4M0=0x00;P4M1=0x00;
  1206.         P5M0=0x00;P5M1=0x00;
  1207.         P6M0=0x00;P6M1=0x00;
  1208.         P7M0=0x00;P7M1=0x00;
  1209.         //设置需要使用的PWM输出口为强推挽模式
  1210.         P2M0=0x0e;
  1211.         P2M1=0x00;
  1212.         P3M0=0x80;
  1213.         P3M1=0x00;
  1214.         
  1215.         P_SW2=0x80;    //最高位置1才能访问和PWM相关的特殊寄存器
  1216.         
  1217.     PWMCFG=0xb0;    //7位6位5位4位3位 2位 1位 0位
  1218.         //置0 1-计数器归零触发ADC C7INI  C6INI  C5INI  C4INI  C3INI  C2INI
  1219.         // 0-归零时不触发ADC  (值为1时上电高电平,为0低电平)   
  1220.         
  1221.         PWMCKS=0x10;        //  置0   0-系统时钟分频   分频参数设定
  1222.                         //  1-定时器2溢出   时钟=系统时钟/([3:0]+1)
  1223.         
  1224.         PWMIF=0x00;    //置0  计数器归零中断标志    相应PWM端口中断标志
  1225.         
  1226.         PWMFDCR=0x00;   //7位    6位  5位   4位     
  1227.         //置0    置0 外部异常检测开关  外部异常时0-无反应 1-高阻状态
  1228.         //3位             2位                 1位                0位      
  1229.     //PWM异常中断  比较器与异常的关系   P2.4与异常的关系  PWM异常标志

  1230.         PWMCH=0x0b;//15位寄存器,决定PWM周期,数值为1-32767,单位:脉冲时钟
  1231.         PWMCL=0xb9;
  1232.         
  1233.         // 以下为每个PWM输出口单独设置
  1234.         PWM2CR=0x00;  //7位6位5位4位   3位      2位       1位        0位
  1235.                         //    置0      输出切换 中断开关 T2中断开关 T1中断开关
  1236.         PWM3CR=0x00;
  1237.         PWM4CR=0x00;
  1238.         PWM5CR=0x00;
  1239.         
  1240.         PWM2T1H=0x0a;
  1241.         //15位寄存器第一次翻转计数  第一次翻转是指从低电平翻转到高电平的计时
  1242.         PWM2T1L=0x8c;
  1243.         PWM2T2H=0x0a;         
  1244.         //15位寄存器第二次翻转计数  第二次翻转是指从高电平翻转到低电平的计时
  1245.         PWM2T2L=0x8d;    //第二次翻转应比精度等级要高,否则会工作不正常
  1246.         // 比如精度1000,第二次翻转就必须小于1000
  1247.          
  1248.         PWM3T1H=0x0a;
  1249.         PWM3T1L=0x8c;
  1250.         PWM3T2H=0x0a;  
  1251.         PWM3T2L=0x8d;
  1252.          
  1253.         PWM4T1H=0x0a;
  1254.     PWM4T1L=0x8c;
  1255.         PWM4T2H=0x0a;  
  1256.         PWM4T2L=0x8d;
  1257.          
  1258.         PWM5T1H=0x0a;
  1259.         PWM5T1L=0x8c;
  1260.         PWM5T2H=0x0a;  
  1261.         PWM5T2L=0x8d;
  1262.         //以上为每个PWM输出口单独设置
  1263. PWMCR=0x8f;   
  1264. //7位/6位5位 4位 3位 2位 1位 0位     10001111
  1265.         //PWM开关 计数归零中断开关   相应I/O为GPIO模式(0)或PWM模式(1)                                                               
  1266.         PWMCKS=0x00;

  1267.         PWM(0,0,0,0);         
  1268. }
  1269. //本函数输入的4个值取值范围为0-3000 0电机停,1000转速最高
  1270. //输入数据不能超过取值范围;
  1271. void PWM(unsigned int PWMa,unsigned int PWMb,unsigned int PWMc,unsigned int PWMd)
  1272. {  
  1273.         PWMa=2700-PWMa;
  1274.         PWMb=2700-PWMb;
  1275.         PWMc=2700-PWMc;
  1276.         PWMd=2700-PWMd;

  1277.         PWM2T1H=PWMa>>8;        
  1278.         //15位寄存器第一次翻转计数  第一次翻转是指从低电平翻转到高电平的计时
  1279.         PWM2T1L= PWMa;

  1280.         PWM3T1H=PWMb>>8;
  1281.         PWM3T1L=  PWMb;

  1282.         PWM4T1H=PWMc>>8;
  1283.         PWM4T1L=  PWMc;

  1284.         PWM5T1H=PWMd>>8;
  1285.         PWM5T1L= PWMd;         
  1286. }
最后说明下和本文配套的STC15开发板目前正在电子发烧友销售,如果需要请戳这里购买: https://bbs.elecfans.com/product/stc15.html  我将持续更新内容。

回帖(19)

孙学荣

2016-4-27 22:00:49
啊u盾萨比传达设计等哈就是的哈时间的哈
举报

马可菠萝

2016-4-28 12:33:01
看一下,比较感兴趣
举报

zhangdonglin

2016-5-10 15:57:15
看看,最近在开始做这个
举报

孙泽文

2016-5-10 16:37:25
赞一个!!!!!!!!!!!!!!
举报

snafceleplay175

2016-5-14 12:18:43
论坛代码的排版有点糟糕,看着累
举报

代码战士

2016-5-17 11:28:31
求这本书的PDF格式。
举报

lee_st

2016-5-25 20:06:35
看看。正在学习中,支持下!
举报

lee_st

2016-5-25 20:07:04
看看。正在学习中,支持下!
举报

lee_st

2016-5-25 20:07:28
看看。正在学习中,支持下!
举报

lee_st

2016-5-25 20:07:41
看看。正在学习中,支持下!
举报

烟艳炎龙

2016-6-16 22:27:00
6666666666666666666666666666666666666666666666666666666666666666666666666
举报

jiangyi

2016-6-25 22:28:44
同求啊,书出版了没啊
举报

Benj

2016-7-25 09:43:20
学习学习
举报

Stonx_sail

2016-9-11 14:16:45
学习。。。。。。。。。。。。。。。。。。。。。
举报

xymbmcu

2016-9-12 11:47:38
引用: jiangyimfs 发表于 2016-6-25 22:28
同求啊,书出版了没啊

书出版了,可以到京东购买了
举报

charlion

2016-11-17 14:11:50
真不错
举报

张仕杰

2016-12-11 10:19:05

谢谢分享谢谢分享谢谢分享
       谢谢分享谢谢分享                       谢谢分享
       谢谢分享谢谢分享                谢谢分享         
                  谢谢分享              谢谢分享谢谢分享谢谢分享
             谢谢分享              谢谢分享        谢                谢
             谢谢分享              谢谢分享        谢                谢
             谢谢分享              谢谢分享        分                分
             谢谢分享              谢谢分享        享                享
             谢谢分享              谢谢分享        谢                谢
             谢谢分享              谢谢分享        谢                谢
谢        谢谢分享               谢谢分享       分                分
谢谢     谢谢分享              谢谢分享        享                享
谢谢分 谢谢分享              谢谢分享        谢                谢
谢谢分 谢谢分享                               谢       谢
谢谢分谢谢分享                         谢                 谢
         谢谢谢谢                    分                               分
             谢谢                   享                                     享
举报

何金明

2018-6-22 16:31:01
受到警告
提示: 作者被禁止或删除 内容自动屏蔽
举报

刘梦想

2018-12-2 23:10:21
四轴飞行器的设计之四轴主板的综合程序——STC15单片机实战指南连载
举报

更多回帖

发帖
×
20
完善资料,
赚取积分