单片机学习小组
直播中

郭雨桐

7年用户 205经验值
私信 关注

STM32F107VC-PC通讯协议

main.c
/****************************************************************************/
/*                                                                          */
/*                Copyright (c) 2016, 老马工作室                            */
/*                     All rights reserved.                                 */
/*                                                                          */
/*      Email:pcwebmaster@163.com                                           */
/****************************************************************************/
/****************************************************************************/
/* 文 件 名:comint.c                                                       */
/* 版    本:Version 1.0                                                    */
/* 描    述:串行口中断带通讯协议测试                                       */
/* 主控芯片:STM32F107VC                                                                                                                                                                                                                */
/* 晶振频率:12MHz                                                                                                                                                                                                          */
/* 作    者: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
#include "hw_config.h"
#include "comint.h"
/*********************************************
*函数名称:void Delay(void)
*
*入口参数:无
*
*出口参数:无
*
*功能说明:简单延时
**********************************************/
void Delay(void)
{
         int x,y;
         for(x=1000;x>0;x--)
                 for(y=1000;y>0;y--);
}

int main(void)
{
   SystemInit();                  //系统初始化
         buff_init();
   NVIC_Configuration();                 //NVIC初始化
   LED_Configuration();                 //LED初始化配置
   USART_Configuration();         //USART初始化
   printf("rn 世界,你好!rn");  
   printf("rn USART1测试正常! rn");
   while(1)
   {
                 com_command_receive();
   }
}
int fputc(int ch, FILE *f)
{
   USART_SendData(USART1, (uint8_t) ch);                                              //发送一个字符
   while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);  //等待发送完成
   return ch;
}

COMINT.C
/****************************************************************************/
/*                                                                          */
/*                Copyright (c) 2016, 老马工作室                            */
/*                     All rights reserved.                                 */
/*                                                                          */
/*      Email:pcwebmaster@163.com                                           */
/****************************************************************************/
/****************************************************************************/
/* 文 件 名:comint.c                                                       */
/* 版    本:Version 1.0                                                    */
/* 描    述:串行口中断带通讯协议测试                                       */
/* 主控芯片:STM32F107VC                                                                                                                                                                                                                */
/* 晶振频率:12MHz                                                                                                                                                                                                          */
/* 作    者: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 "comint.h"

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


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

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

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

/* 串口发送一个字节 */
void com_send_command(uint16_t Data)
{
   /* Check the parameters */
   assert_param(IS_USART_ALL_PERIPH(USART1));
   assert_param(IS_USART_DATA(Data));

   /* Transmit Data */
   USART1->DR = (Data & (uint16_t)0x01FF);
         while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);  //等待发送完成
}

/* 串口接收数据处理 */
void com_command_receive(void)
{
     uint8_t var1,var4;
     uint16_t crc_data = 0;
     var4 = pint_read;

     if (var4 != pint_write)
     {
         var1 = pint_buf[var4];
         var4 = var4+1;
         if (var4 >= MAX_RINTL)
             var4=0;

         pint_read = var4;

         switch(serial_flag)
         {
             case 0: /*收到起始位*/
                 if (var1 == SYN)
                 {
                     serial_flag = 1;
//com_send_command(0x01); //测试
                 }
                 else
                 {
                     serial_flag = 0;
                 }
                 break;

             case 1:/*收到起始位*/
                 if (var1 == SYN)
                 {
                     serial_flag = 2;
//com_send_command(0x02); //测试
                 }
                 else
                 {
                     serial_flag = 0;
                 }
                 break;

             case 2:/*收到同步位*/
                 if (var1 == STX)
                 {
                     serial_flag = 3;
//com_send_command(0x03);//测试
                 }
                 else
                 {
                     serial_flag = 0;
                 }
                 break;

             case 3: /*收到组地址*/
                 if (var1 == ADDRESS[0])
                 {
                     serial_flag = 4;
                     prec_num = 1;
                     prec_buf[0] = var1;
//com_send_command(0x04); //测试
                 }
                 else
                 {
                     serial_flag = 0;
                 }
                 break;

             case 4:/*收到本机地址或者广播地址*/
                 if ( (var1 == ADDRESS[1]) || (var1 == 0) )
                 {
                     prec_num = 2;
                     prec_buf[1] = var1;
                     serial_flag = 5;
//com_send_command(0x05); //测试
                 }
                 else
                 {
                     serial_flag = 0;
                 }
                 break;

             case 5:/*数据长度*/
                 prec_num = 3;
                 prec_buf[2] = var1;
                 serial_lengthl = var1;
                 serial_flag = 6;
//com_send_command(0x06);//测试
                 break;

             case 6:
                 prec_num = 4;
                 prec_buf[3] = var1;
                 serial_length |= var1;
                 serial_length = ( (serial_length << 8) & 0xff00 ) + serial_lengthl + 3;
                 serial_flag = 7;
//com_send_command(0x07);//测试
                 break;

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

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

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

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

send_command(NAK); //测试
                         }
                     }
                     else
                     {

send_command(NAK); //测试
                     }
                     serial_flag = 0;
                     prec_num = 1;
                 }
                 break;

             default:
                 serial_flag = 0;
                 prec_num = 1;
                 break;
         }
     }
}
/* 命令解码子程序 */
void command_decoder(void)
{
//    uint8_t i = 0;

     if (prec_buf[4] == 0x31)       /* 设置报警阈值   */
     {                  
com_send_command(0x11);//测试
         return;
     }
     else if (prec_buf[4] == 0x32)  /* 请求报警阈值 */
     {
com_send_command(0x12);//测试?
         return;
     }
     else if (prec_buf[4] == 0x33)  /* 修改当前时间 */
     {
com_send_command(0x13);//测试
         return;
     }
     else if (prec_buf[4] == 0x34)  /* 请求当前时间 */
     {
com_send_command(0x14);//测试
         return;
     }
     else if (prec_buf[4] == 0x35)  /* 请求当前数据 */
     {
com_send_command(0xAA);//测试        
//__nop();
com_send_command(0x15);//测试
         return;
     }
     else if (prec_buf[4] == 0x36)  /* 请求看门狗信息*/
     {
com_send_command(0x16);//测试
         return;
     }
     else if (prec_buf[4] == 0x37)  /* 请求报警情况 */
     {
com_send_command(0x17);//测试
         return;
     }
     else if (prec_buf[4] == 0x38)  /* 配置设备地址 */
     {
         ADDRESS[0] = prec_buf[5];  /* 通讯组地址   */
         ADDRESS[1] = prec_buf[6];  /* 开发板地址   */
com_send_command(0x181);//测试
         return;
     }
     else if (prec_buf[4] == 0x39)  /* 请求设备地址 */
     {
com_send_command(0x19);//测试
         return;
     }
     else if (prec_buf[4] == 0x3a)  /* 控制模拟量输出 */
     {
com_send_command(0x1A);//测试?
         return;
     }
     else if (prec_buf[4] == 0x3b)  /* 控制开关量输出 */
     {
com_send_command(0x1B);//测试
         return;
     }
//                if (prec_buf[4] == 0x00)       /* 如果是广播地址  */
//    {                  
//                                com_send_command(SYN);
//                                com_send_command(0x00);
//                                com_send_command(SYN);
//        return;
//    }
}

/* 向PC主机发送消息帧,入口参数:消息类型 */
void send_command(uint8_t command)
{
     switch (command)
     {
         case ACK:
             com_send_command(SYN);
             com_send_command(SYN);
             com_send_command(ACK);
             break;

         case NAK:
             com_send_command(SYN);
             com_send_command(SYN);
             com_send_command(NAK);
             break;

         default:
             break;
     }
}
void buff_init(void)
{
     uint8_t loop;
     loop = USART_ReceiveData(USART1);   /* 清串口缓冲区   */
     for (loop=0; loop      {
         pint_buf[loop] = 0;
     }
}
/*计算CRC校验和使用MTT(0X1021)
参数:
pBuff 为需计算CRC的缓冲区的头指针
BufferLen 缓冲区长度(以字节计)
*/
u_short CalCRC16_1021(uint8_t x[], u_short BufferLen)
{
     u_short i;
     uint8_t  j;
     u_short crc16 = 0;
     u_short mask = 0x1021;
     uint8_t *pByteBuffer;
     uint8_t tmpbyte;
     u_short calval;

     pByteBuffer = &x[0];

     for (i = 0; i < BufferLen; i++)
     {
         tmpbyte = *pByteBuffer;
         calval = tmpbyte << 8;
         for (j = 0; j < 8; j++)
         {
             if ((crc16 ^ calval) & 0x8000)
                 crc16 = (crc16 << 1) ^ mask;
             else
                 crc16 <<= 1;

             calval <<= 1;
         }
         pByteBuffer++;
     }
     return crc16;
}

/***************************************************
*函数名称:void USART1_IRQHandler(void)
*
*入口参数:无
*
*出口参数:无
*
*功能说明:USART1接收中断
*****************************************************/
void USART1_IRQHandler(void)
{
     uint8_t temp;
     uint8_t temp1;        
         
         if(USART_GetITStatus(USART1, USART_IT_RXNE)==SET)
         {
                 USART_ClearITPendingBit(USART1, USART_IT_RXNE);
                 temp1=USART_ReceiveData(USART1);
                 temp  = pint_write + 1; /* 判断是否可以写入 */
                 if (temp == MAX_RINTL)
                 {
                                 temp=0;
                 }
                 if (temp != pint_read)
                 {
                                 pint_buf[pint_write] = temp1; /* 读取数据 */
                                 pint_write = temp;
                 }
         }
}


COMINT.h
#ifndef __COMINT_H__
#define __COMINT_H__

#include "hw_config.h"
typedef        unsigned short        u_short;

#define ZU                        0x01                 /*组地址*///通讯地址修改这两项
#define ZHAN                0x02                 /*站地址*///通讯地址修改这两项

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

#define ACK           0x06
#define NAK           0x15

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

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

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

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

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

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

#endif





更多回帖

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