基于STM32的USART、UART串口命令调制和解析(加密与解密)
采用芯片为STM32F407ZG
调制后的命令采用USART1往外发送 发送至USART2
而后USART2接收命令后 进行解析 把命令中有用的部分提取出来 再向外发送控制命令
同时 USART1接收外部命令后 也可以转发给USART2
命令格式为:
起始位 2Byte 0x07 0xCD
数据长度位 2Byte 默认 0x00 0x08
数据流 16Byte 这里是用八个点的坐标值(x,y)来模拟
校验码 2Byte 前20位数据之和
停止位 2Byte 0x04 0xBC
资源:
https://download.csdn.net/download/weixin_53403301/86401762
在解析部分 要从结构体中将坐标提取出来
struct Point_Position{
uint8_t x;
uint8_t y;
uint8_t vx;
uint8_t vy;
uint8_t angle;
};
即里面的x y
USART1_RX中断为发送接收的数据
USART2_RX中断为发送解析后的数据
代码如下:
#include "stm32f4xx.h"
#include "DELAY.h"
uint8_t rx_data_buf[24];
uint8_t send_data_buf[]={0,0,0,0,0x00,0x20,0xF8,0x00};
uint8_t usart2_flag=0;
uint8_t begain_data_buf[]={0x5a,0xa5,0x67,0x82,0x54,0x40,0x00,0x05,0x00,0x08};
uint8_t flag=0;
struct Point_Position{
uint8_t x;
uint8_t y;
uint8_t vx;
uint8_t vy;
uint8_t angle;
};
struct Point_Position Point[8] = {
{.x=5, .y=10, .vx=0,.vy=0,.angle=0},
{.x=8, .y=7, .vx=0,.vy=0,.angle=0},
{.x=14, .y=9, .vx=0,.vy=0,.angle=0},
{.x=9, .y=13, .vx=0,.vy=0,.angle=0},
{.x=25, .y=23, .vx=0,.vy=0,.angle=0},
{.x=7, .y=15, .vx=0,.vy=0,.angle=0},
{.x=12, .y=22, .vx=0,.vy=0,.angle=0},
{.x=15, .y=12, .vx=0,.vy=0,.angle=0}
};
void init_USART1(uint32_t Baud)
{
//定义GPIO结构体
GPIO_InitTypeDef GPIO_KEEY_InitStruct;
//使能GPIOF时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//初始化结构体
GPIO_KEEY_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //定义引脚
GPIO_KEEY_InitStruct.GPIO_Mode = GPIO_Mode_AF; //定义输出模式
GPIO_KEEY_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; //定义速度
GPIO_KEEY_InitStruct.GPIO_OType = GPIO_OType_PP; //定义推挽输出
GPIO_KEEY_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; //定义是否有上下拉电阻 普通
//将结构体给GPIOF组
GPIO_Init(GPIOA,&GPIO_KEEY_InitStruct);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); //复用功能
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); //复用功能
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//配置串口
USART_InitStructure.USART_BaudRate = Baud; //波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位数据位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //支持收发数据
USART_Init(USART1, &USART_InitStructure);
//中断方式
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能RX
//中断优先级
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//使能串口
USART_Cmd(USART1, ENABLE);
}
void init_USART2(uint32_t Baud)
{
//定义GPIO结构体
GPIO_InitTypeDef GPIO_KEEY_InitStruct;
//使能GPIOF时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//初始化结构体
GPIO_KEEY_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; //定义引脚
GPIO_KEEY_InitStruct.GPIO_Mode = GPIO_Mode_AF; //定义输出模式
GPIO_KEEY_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; //定义速度
GPIO_KEEY_InitStruct.GPIO_OType = GPIO_OType_PP; //定义推挽输出
GPIO_KEEY_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; //定义是否有上下拉电阻 普通
//将结构体给GPIOF组
GPIO_Init(GPIOA,&GPIO_KEEY_InitStruct);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); //复用功能
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); //复用功能
USART_InitTypeDef USART_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
//配置串口
USART_InitStructure.USART_BaudRate = Baud; //波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位数据位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //支持收发数据
USART_Init(USART2, &USART_InitStructure);
//中断方式
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //使能RX
//中断优先级
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//使能串口
USART_Cmd(USART2, ENABLE);
}
int main(void)
{
init_USART1(115200);
init_USART2(115200);
USART_Cmd(USART2, DISABLE);
uint8_t data_buf[24];
uint16_t check_sum=0;
uint8_t i=0;
data_buf[0]=0x07;
data_buf[1]=0xCD;
data_buf[2]=0x00;
data_buf[3]=0x08;
data_buf[22]=0x04;
data_buf[23]=0xBC;
for(i=0;i<8;i++)
{
data_buf[4+i*2]=Point[i].x;
data_buf[5+i*2]=Point[i].y;
}
for(i=0;i<20;i++)
{
check_sum = data_buf[i] + check_sum;
}
data_buf[20] = ((check_sum>>8)&0x00FF)&0xFF;
data_buf[21] = ((check_sum>>0)&0x00FF)&0xFF;
while(1)
{
USART_Cmd(USART2, ENABLE);
for(i=0;i<24;i++)
{
flag=1;
char DATA1=data_buf[i];
USART_SendData(USART1,DATA1);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
while(flag);
}
delay_ms(500);
USART_Cmd(USART2, DISABLE);
delay_ms(500);
}
}
//串口1中断服务函数
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
char data = USART_ReceiveData(USART1);
USART_SendData(USART1,data);
USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清空标志位
}
}
void USART2_IRQHandler(void)
{
uint8_t k=0;
uint8_t j=0;
if(USART_GetITStatus(USART2,USART_IT_RXNE)==SET)
{
flag=0;
char DATA2=USART_ReceiveData(USART2);
rx_data_buf[usart2_flag]=DATA2;
usart2_flag++;
if (usart2_flag==24)
{
usart2_flag=0;
if(rx_data_buf[0]==0x07 && rx_data_buf[1]==0xCD && rx_data_buf[22]==0x04 && rx_data_buf[23]==0xBC )
{
for(k=0;k<10;k++)
{
USART_SendData(USART2,begain_data_buf[k]);
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
}
for(k=0;k<8;k++)
{
send_data_buf[1]=rx_data_buf[4+2*k];
send_data_buf[3]=rx_data_buf[5+2*k];
for(j=0;j<8;j++)
{
USART_SendData(USART2,send_data_buf[j]);
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
// USART_ClearITPendingBit(USART2,USART_IT_RXNE);//清空标志位
}
}
USART_SendData(USART2,0xFF);
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
USART_SendData(USART2,0x00);
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
}
}
USART_ClearITPendingBit(USART2,USART_IT_RXNE);//清空标志位
}
}
在USART2中断中 值判断了起始位和停止位 没有判断数据长度和校验码 如果加上判断 可以更加精确
全局变量flag 是对时序用的 如果USART1用另外一个mcu来发送的话 则可以发出一个使能信号CS 来对时序