[DemoCode下载] NuMicro M0516-PC通讯协议

[复制链接]
1296|7
 楼主| 500days 发表于 2016-5-20 21:41 | 显示全部楼层 |阅读模式
/****************************************************************************/
/*                                                                          */
/*                Copyright (c) 2016, 老马工作室                            */
/*                     All rights reserved.                                 */
/*                                                                          */
/*      Email:pcwebmaster@163.com                                           */
/****************************************************************************/
/****************************************************************************/
/* 文 件 名:comint.c                                                       */
/* 版    本:Version 1.0                                                    */
/* 描    述:串行口中断带通讯协议测试                                       */
/* 主控芯片:NuMicro M0516*/
/* 晶振频率:11.0592MHz          */
/* 作    者:pcwebmaster(北极狼)                                            */
/* 函    数:                                                               */
/*         system_init                                                     */
/*         com_send_command                                                */
/*         com_command_receive*/
/*CalCRC16_1021*/
/*command_decoder*/
/*send_command*/
/* 测    试: 发送:16 16 02 01 02 01 00 35 03 94 BD接收:49 AA 15 */
/* 测试现象:  */
/* 历史记录:20016.02.18测试通过                                            */
/* 北极狼          20016-02-18     Creat Inital version. (Version 1.0)      */
/****************************************************************************/
#include <stdio.h>
#include "M051Series.h"
#include "comint.h"
#define PLL_CLOCK           50000000

/*---------------------------------------------------------------------------------------------------------*/
/* Global variables                                                                                        */
/*---------------------------------------------------------------------------------------------------------*/

void SYS_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Enable Internal RC 22.1184MHz clock */
    CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);
    /* Waiting for Internal RC clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);
    /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
    CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));
    /* Enable external XTAL 12MHz clock */
    CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);
    /* Waiting for external XTAL clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);
    /* Set core clock as PLL_CLOCK from PLL */
    CLK_SetCoreClock(PLL_CLOCK);
    /* Enable UART module clock */
    CLK_EnableModuleClock(UART0_MODULE);
    /* Select UART module clock source */
//    CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));CLK_CLKSEL1_UART_S_HIRC
    CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HIRC, CLK_CLKDIV_UART(1));
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Set P3 multi-function pins for UART0 RXD and TXD */
    SYS->P3_MFP &= ~(SYS_MFP_P30_Msk | SYS_MFP_P31_Msk);
    SYS->P3_MFP |= (SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0);
}

 楼主| 500days 发表于 2016-5-20 21:42 | 显示全部楼层
  1. void UART0_Init()
  2. {
  3.     /*---------------------------------------------------------------------------------------------------------*/
  4.     /* Init UART                                                                                               */
  5.     /*---------------------------------------------------------------------------------------------------------*/
  6.     /* Reset IP */
  7.     SYS_ResetModule(UART0_RST);
  8.     /* Configure UART0 and set UART0 Baudrate */
  9.     UART_Open(UART0, 115200);
  10. //UART_Open(UART0, 9600);
  11.     /* Enable Interrupt and install the call back function */
  12.     UART_ENABLE_INT(UART0, (UART_IER_RDA_IEN_Msk));// | UART_IER_THRE_IEN_Msk | UART_IER_RTO_IEN_Msk));
  13.     NVIC_EnableIRQ(UART0_IRQn);
  14. //    while(g_bWait);
  15. }

  16. void Uart0Send(int32_t Bytes)
  17. {
  18. UART0->THR = Bytes;
  19. while ((UART0->FSR&TX_EMPTY) != 0x00); //检查发送FIFO是否为空
  20. }
  21. /*---------------------------------------------------------------------------------------------------------*/
  22. /* MAIN function                                                                                           */
  23. /*---------------------------------------------------------------------------------------------------------*/

  24. int main(void)
  25. {
  26. //int8_t  i,j;   
  27.     SYS_UnlockReg();/* Unlock protected registers */   
  28.     SYS_Init();/* Init System, IP clock and multi-function I/O */   
  29.     SYS_LockReg();/* Lock protected registers */   
  30.     UART0_Init();/* Init UART0 for printf and testing */
  31. buff_init();
  32.     /*---------------------------------------------------------------------------------------------------------*/
  33.     /* SAMPLE CODE                                                                                             */
  34.     /*---------------------------------------------------------------------------------------------------------*/
  35.     printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %dHz\n", SystemCoreClock);
  36. printf("\r\n 世界,你好!\r\n");  
  37. printf("\r\n USART0测试正常! \r\n");
  38. while(1)
  39. {
  40. com_command_receive();
  41. }
  42. }

  43. COMINT.C
  44. /****************************************************************************/
  45. /*                                                                          */
  46. /*                Copyright (c) 2016, 老马工作室                            */
  47. /*                     All rights reserved.                                 */
  48. /*                                                                          */
  49. /*      Email:pcwebmaster@163.com                                           */
  50. /****************************************************************************/
  51. /****************************************************************************/
  52. /* 文 件 名:comint.c                                                       */
  53. /* 版    本:Version 1.0                                                    */
  54. /* 描    述:串行口中断带通讯协议测试                                       */
  55. /* 主控芯片:NuMicro M0516*/
  56. /* 晶振频率:11.0592MHz          */
  57. /* 作    者:pcwebmaster(北极狼)                                            */
  58. /* 函    数:                                                               */
  59. /*         system_init                                                     */
  60. /*         com_send_command                                                */
  61. /*         com_command_receive*/
  62. /*CalCRC16_1021*/
  63. /*command_decoder*/
  64. /*send_command*/
  65. /* 测    试: 发送:16 16 02 01 02 01 00 35 03 94 BD接收:49 AA 15 */
  66. /* 测试现象:  */
  67. /* 历史记录:20016.02.18测试通过                                            */
  68. /* 北极狼          20016-02-18     Creat Inital version. (Version 1.0)      */
  69. /****************************************************************************/
  70. #include "comint.h"

  71. uint8_t  pint_buf[MAX_RINTL];   /* 串口接收缓冲区       */
  72. uint8_t  pint_read;             /* 串口缓冲区读指针     */
  73. uint8_t  pint_write;            /* 串口缓冲区写指针     */
  74. uint8_t  psend_int;             /* 串口发送允许标志     */
  75. uint8_t  serial_flag = 0;       /* 串口接收数据标志位   */


  76. uint8_t  prec_buf[MAX_COMMAND_LEN];/* 命令接收缓冲区    */
  77. uint8_t  prec_num;                    /* 命令接收缓冲区字节数 */

  78. uint8_t serial_lengthl = 0;           /* 消息命令长度低8位    */
  79. uint16_t  serial_length = 0;          /* 消息命令长度16位     */

  80. uint8_t ADDRESS[2]={ZU,ZHAN};       /* byte0:通讯组地址, byte1:开发板地址 */


 楼主| 500days 发表于 2016-5-20 21:43 | 显示全部楼层
  1. /* 串口发送一个字节 */
  2. void com_send_command(uint16_t Data)
  3. {
  4. UART0->THR = Data;
  5. while ((UART0->FSR&TX_EMPTY) != 0x00); //检查发送FIFO是否为空
  6. }

  7. /* 串口接收数据处理 */
  8. void com_command_receive(void)
  9. {
  10.     uint8_t var1,var4;
  11.     uint16_t crc_data = 0;
  12.     var4 = pint_read;

  13.     if (var4 != pint_write)
  14.     {
  15.         var1 = pint_buf[var4];
  16.         var4 = var4+1;
  17.         if (var4 >= MAX_RINTL)
  18.             var4=0;

  19.         pint_read = var4;

  20.         switch(serial_flag)
  21.         {
  22.             case 0: /*收到起始位*/
  23.                 if (var1 == SYN)
  24.                 {
  25.                     serial_flag = 1;
  26. //com_send_command(0x01); //测试
  27.                 }
  28.                 else
  29.                 {
  30.                     serial_flag = 0;
  31.                 }
  32.                 break;

  33.             case 1:/*收到起始位*/
  34.                 if (var1 == SYN)
  35.                 {
  36.                     serial_flag = 2;
  37. //com_send_command(0x02); //测试
  38.                 }
  39.                 else
  40.                 {
  41.                     serial_flag = 0;
  42.                 }
  43.                 break;

  44.             case 2:/*收到同步位*/
  45.                 if (var1 == STX)
  46.                 {
  47.                     serial_flag = 3;
  48. //com_send_command(0x03);//测试
  49.                 }
  50.                 else
  51.                 {
  52.                     serial_flag = 0;
  53.                 }
  54.                 break;

  55.             case 3: /*收到组地址*/
  56.                 if (var1 == ADDRESS[0])
  57.                 {
  58.                     serial_flag = 4;
  59.                     prec_num = 1;
  60.                     prec_buf[0] = var1;
  61. //com_send_command(0x04); //测试
  62.                 }
  63.                 else
  64.                 {
  65.                     serial_flag = 0;
  66.                 }
  67.                 break;

  68.             case 4:/*收到本机地址或者广播地址*/
  69.                 if ( (var1 == ADDRESS[1]) || (var1 == 0) )
  70.                 {
  71.                     prec_num = 2;
  72.                     prec_buf[1] = var1;
  73.                     serial_flag = 5;
  74. //com_send_command(0x05); //测试
  75.                 }
  76.                 else
  77.                 {
  78.                     serial_flag = 0;
  79.                 }
  80.                 break;

  81.             case 5:/*数据长度*/
  82.                 prec_num = 3;
  83.                 prec_buf[2] = var1;
  84.                 serial_lengthl = var1;
  85.                 serial_flag = 6;
  86. //com_send_command(0x06);//测试
  87.                 break;

  88.             case 6:
  89.                 prec_num = 4;
  90.                 prec_buf[3] = var1;
  91.                 serial_length |= var1;
  92.                 serial_length = ( (serial_length << 8) & 0xff00 ) + serial_lengthl + 3;
  93.                 serial_flag = 7;
  94. //com_send_command(0x07);//测试
  95.                 break;

  96.             case 7:
  97.                 prec_buf[prec_num] = var1;
  98.                 prec_num++;
  99.                 serial_length--;
  100.                 if (serial_length == 0)
  101.                 {
  102.                     crc_data = CalCRC16_1021(prec_buf, prec_num - 2); /* 计算crc校验和(从组地址开始到ETX )*/

  103.                     if ( ( (crc_data & 0x00ff) == prec_buf[prec_num - 2]) && ( ( (crc_data >>8) & 0x00ff) == prec_buf[prec_num - 1]) ) /* 校验和正确 */
  104.                     {
  105.                         prec_num = 1;
  106.                         var1 = 0;

  107.                         if ( (prec_buf[4] >= 0x31) && (prec_buf[4] <= 0x3b) ) /* 命令有效 */
  108.                         {
  109.                             if (prec_buf[1] != 0x00) /* 如果不是广播地址则回应ACK*/
  110. com_send_command(0x49);//测试                                 msg_last_push(MSG_ACK,0);
  111. //send_command(ACK); //测试   

  112.                             command_decoder(); /* 如果校验和正确,则进行命令解码 */
  113.                         }
  114.                         else
  115.                         {

  116. send_command(NAK); //测试
  117.                         }
  118.                     }
  119.                     else
  120.                     {

  121. send_command(NAK); //测试
  122.                     }
  123.                     serial_flag = 0;
  124.                     prec_num = 1;
  125.                 }
  126.                 break;

  127.             default:
  128.                 serial_flag = 0;
  129.                 prec_num = 1;
  130.                 break;
  131.         }
  132.     }
  133. }


 楼主| 500days 发表于 2016-5-20 21:44 | 显示全部楼层
  1. /* 命令解码子程序 */
  2. void command_decoder(void)
  3. {
  4. //    uint8_t i = 0;

  5.     if (prec_buf[4] == 0x31)       /* 设置报警阈值   */
  6.     {  
  7. com_send_command(0x11);//测试
  8.         return;
  9.     }
  10.     else if (prec_buf[4] == 0x32)  /* 请求报警阈值 */
  11.     {
  12. com_send_command(0x12);//测试?
  13.         return;
  14.     }
  15.     else if (prec_buf[4] == 0x33)  /* 修改当前时间 */
  16.     {
  17. com_send_command(0x13);//测试
  18.         return;
  19.     }
  20.     else if (prec_buf[4] == 0x34)  /* 请求当前时间 */
  21.     {
  22. com_send_command(0x14);//测试
  23.         return;
  24.     }
  25.     else if (prec_buf[4] == 0x35)  /* 请求当前数据 */
  26.     {
  27. com_send_command(0xAA);//测试
  28. //__nop();
  29. com_send_command(0x15);//测试
  30.         return;
  31.     }
  32.     else if (prec_buf[4] == 0x36)  /* 请求看门狗信息*/
  33.     {
  34. com_send_command(0x16);//测试
  35.         return;
  36.     }
  37.     else if (prec_buf[4] == 0x37)  /* 请求报警情况 */
  38.     {
  39. com_send_command(0x17);//测试
  40.         return;
  41.     }
  42.     else if (prec_buf[4] == 0x38)  /* 配置设备地址 */
  43.     {
  44.         ADDRESS[0] = prec_buf[5];  /* 通讯组地址   */
  45.         ADDRESS[1] = prec_buf[6];  /* 开发板地址   */
  46. com_send_command(0x181);//测试
  47.         return;
  48.     }
  49.     else if (prec_buf[4] == 0x39)  /* 请求设备地址 */
  50.     {
  51. com_send_command(0x19);//测试
  52.         return;
  53.     }
  54.     else if (prec_buf[4] == 0x3a)  /* 控制模拟量输出 */
  55.     {
  56. com_send_command(0x1A);//测试?
  57.         return;
  58.     }
  59.     else if (prec_buf[4] == 0x3b)  /* 控制开关量输出 */
  60.     {
  61. com_send_command(0x1B);//测试
  62.         return;
  63.     }
  64. //if (prec_buf[4] == 0x00)       /* 如果是广播地址  */
  65. //    {  
  66. //com_send_command(SYN);
  67. //com_send_command(0x00);
  68. //com_send_command(SYN);
  69. //        return;
  70. //    }
  71. }


 楼主| 500days 发表于 2016-5-20 21:44 | 显示全部楼层
  1. /* 向PC主机发送消息帧,入口参数:消息类型 */
  2. void send_command(uint8_t command)
  3. {
  4.     switch (command)
  5.     {
  6.         case ACK:
  7.             com_send_command(SYN);
  8.             com_send_command(SYN);
  9.             com_send_command(ACK);
  10.             break;

  11.         case NAK:
  12.             com_send_command(SYN);
  13.             com_send_command(SYN);
  14.             com_send_command(NAK);
  15.             break;

  16.         default:
  17.             break;
  18.     }
  19. }
  20. void buff_init(void)
  21. {
  22.     uint8_t loop;
  23.     loop = UART0->RBR;   /* 清串口缓冲区   */
  24.     for (loop=0; loop<MAX_RINTL; loop++)
  25.     {
  26.         pint_buf[loop] = 0;
  27.     }
  28. }
  29. /*计算CRC校验和使用MTT(0X1021)
  30. 参数:
  31. pBuff 为需计算CRC的缓冲区的头指针
  32. BufferLen 缓冲区长度(以字节计)
  33. */
  34. u_short CalCRC16_1021(uint8_t x[], u_short BufferLen)
  35. {
  36.     u_short i;
  37.     uint8_t  j;
  38.     u_short crc16 = 0;
  39.     u_short mask = 0x1021;
  40.     uint8_t *pByteBuffer;
  41.     uint8_t tmpbyte;
  42.     u_short calval;

  43.     pByteBuffer = &x[0];

  44.     for (i = 0; i < BufferLen; i++)
  45.     {
  46.         tmpbyte = *pByteBuffer;
  47.         calval = tmpbyte << 8;
  48.         for (j = 0; j < 8; j++)
  49.         {
  50.             if ((crc16 ^ calval) & 0x8000)
  51.                 crc16 = (crc16 << 1) ^ mask;
  52.             else
  53.                 crc16 <<= 1;

  54.             calval <<= 1;
  55.         }
  56.         pByteBuffer++;
  57.     }
  58.     return crc16;
  59. }
 楼主| 500days 发表于 2016-5-20 21:45 | 显示全部楼层
  1. /*---------------------------------------------------------------------------------------------------------*/
  2. /* ISR to handle UART Channel 0 interrupt event                                                            */
  3. /*---------------------------------------------------------------------------------------------------------*/
  4. void UART0_IRQHandler(void)
  5. {
  6.     uint8_t temp;
  7.     uint8_t temp1;

  8. if(UART0->ISR & RDA_INT) //检查是否接收数据中断
  9. {
  10. while(UART0->ISR & RDA_IF)  //获取所有接收到的数据
  11. {
  12. while (UART0->FSR & RX_EMPTY); //检查接收FIFO是否为空
  13. temp1 = UART0->RBR; //读取数据
  14. temp  = pint_write + 1; /* 判断是否可以写入 */
  15. if (temp == MAX_RINTL)
  16. {
  17. temp=0;
  18. }
  19. if (temp != pint_read)
  20. {
  21. pint_buf[pint_write] = temp1; /* 读取数据 */
  22. pint_write = temp;
  23. }
  24. }
  25. }
  26. }

  27. COMINT.h

  28. #ifndef __COMINT_H__
  29. #define __COMINT_H__

  30. #include <stdio.h>
  31. #include "M051Series.h"

  32. #define RXBUFSIZE 8//1024
  33. #define TX_EMPTY(1<<22)
  34. #define RX_EMPTY(1<<14)
  35. #define RDA_INT(1<<8)
  36. #define RDA_IF(1<<0)

  37. typedefunsigned shortu_short;

  38. #define ZU0x01 /*组地址*///通讯地址修改这两项
  39. #define ZHAN0x02 /*站地址*///通讯地址修改这两项

  40. #define MAX_RINTL       16   /* 串口接收缓冲区长度   */
  41. #define SYN           0x16   /* 通讯同步位*/
  42. #define STX           0x02   /* 通讯起始位*/
  43. #define ETX           0x03   /* 通讯结束位*/

  44. #define ACK           0x06
  45. #define NAK           0x15

  46. #define MSG_ACK          2    /* 正确应答信息         */
  47. #define MSG_NAK          3    /* 错误应答信息         */
  48. #define MAX_COMMAND_LEN  16   /* 串口接受命令长度     */

  49. extern char str_test[25]  ;
  50. extern uint8_t  pint_read;             // 串口缓冲区读指针     */
  51. extern uint8_t  pint_write;            // 串口缓冲区写指针
  52. //extern uint8_t  data  psend_int;             // 串口发送允许标志   
  53. extern uint8_t  pint_buf[MAX_RINTL];   // 串口接收缓冲区      
  54. extern uint8_t serial_flag;              /* 串口接收数据标志位   */

  55. extern uint8_t  prec_buf[MAX_COMMAND_LEN];/* 命令接收缓冲区 */

  56. /* 串口发送一个字节 */
  57. extern void com_send_command(uint16_t Data);
  58. /* 串口接收数据处理 */
  59. extern void com_command_receive(void);
  60. /* 串口接收初始化 */
  61. extern void buff_init(void);

  62. ///* 串口接收一字节数据 */
  63. //unsigned char UartReadChar(void); //reentrant
  64. /*计算CRC校验和使用MTT(0X1021)
  65. 参数:
  66. pBuff 为需计算CRC的缓冲区的头指针
  67. BufferLen 缓冲区长度(以字节计)
  68. */
  69. u_short CalCRC16_1021(uint8_t x[], u_short BufferLen);

  70. /* 命令解码子程序 */
  71. void command_decoder(void);
  72. /* 向主机发送消息帧,入口参数:消息类型 */
  73. void send_command(uint8_t command);

  74. #endif
wahahaheihei 发表于 2016-5-21 17:12 | 显示全部楼层
楼主的标题太晃人了,直接写串口通信就行了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

120

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部