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 |
更多回帖