基于STM32F103C8T6的USART串行通信(PC与STM32) 一、功能要求及通信协议设计 通过PC控制STM32最小系统上的LED。采用中断接收法,当串口接收到数据即进入中断函数,接收该数据。接收和发送的数据帧长度可变,但不超过255字节。 通信协议设计如下: 1. PC端 (1) 数据帧头为0xEA,数据帧尾为0x55。 (2) 如果数据帧中间数据为0x01,表示要点亮相对应的LED。 (3) 如果数据帧中间数据为0x02,表示要关闭相对应的LED。 2. STM32实验系统端 (1) 正确点亮LED,则STM32回发:“LED in STM32 has been turnon!”,否则回发:“LED in STM32 has been on!”。 (2) 正确关闭LED,则STM32回发:“LED in STM32 has been turnoff!”,否则回发:“LED in STM32 has been off!”。 二、程序算法1. 算法设计 上位机(这里采用PC)按通信协议要求发送一帧数据给STM32实验系统(下位机),下位机以中断方式接收数据帧,如果是有效数据帧则设置标志,否则清除标志;如果接收到有效数据帧,STM32实验系统(下位机)对数据帧进行分析并进行相应处理。如果命令是0x01,则点亮LED;如果命令是0x02,则关闭LED。 2. 程序框架 由于采用中断方式,因此工程模板中的两个中断相关文件均必须被使用:stm32f10x_it.h和stm32f10x_it.c,前者主要是进行全局变量说明、中断函数说明,后者主要是中断函数的定义。另外设计的文件是:main.c,stm32f10x_conf.h,前者是主函数所在文件,后者是功能模块头文件设置文件。其它自定义文件有:UserDefine.h和User.c,前者是用户类型定义及函数声明所在文件,后者是用户函数定义所在文件。因此,涉及工程模板中的文件有4个,分别是: (1) stm32f10x_it.h; (2) stm32f10x_it.c; (3) stm32f10x_conf.h; (4) main.c; (5) UserDefine.h; (6) User.c。 三、工程配置1. 选择设备为STM32F103C8
2. 修改晶振频率为8.0 STM32F103C8的内部晶振频率为8MHz。 3. 设置预处理宏定义符号:USE_STDPERIPH_DRIVER,STM32F10X_MD USE_STDPERIPH_DRIVER表示要使用固件库,STM32F10X_MD表示选用的是中等容量的STM32芯片。 4. 设置IncludePath路径 该项配置是为了将STM32的启动文件及官方库包含进项目中,这样能加快开发速度,而且使用官方库开发相较于其他方式而言更浅显易懂。 5. 设置调试方式 此项为PC与STM32芯片的连接方式,具体请自行调整 6. 设置启动方式 此项设置为程序下载后及启动,免去了手动启动的环节。 四、源程序1. 文件1——stm32f10x_it.h #ifndef __STM32F10x_IT_H #define __STM32F10x_IT_H #include "stm32f10x.h" #include "UserDefine.h" void NMI_Handler(void); void HardFault_Handler(void); void MemManage_Handler(void); void BusFault_Handler(void); void UsageFault_Handler(void); void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); void USART1_IRQHandler(void); #endif /* __STM32F10x_IT_H */
2. 文件2——stm32f10x_it.c #include "stm32f10x_it.h" extern RxTxBuffer_t Data; void NMI_Handler(void) { } void HardFault_Handler(void) { /* Go to infinite loop when Hard Faultexception occurs */ while (1) { } } void MemManage_Handler(void) { /* Go to infinite loop when Memory Manageexception occurs */ while (1) { } }
void BusFault_Handler(void) { /* Go to infinite loop when Bus Fault exception occurs */ while (1) { } }
void UsageFault_Handler(void) { /* Go to infinite loop when Usage Faultexception occurs */ while (1) { } }
void SVC_Handler(void) { } void DebugMon_Handler(void) { } void PendSV_Handler(void) { } void SysTick_Handler(void) { } void USART1_IRQHandler(void) { if(USART_GetFlagStatus(USART1,USART_IT_RXNE)!=RESET) { USART_ClearITPendingBit(USART1, USART_IT_RXNE); Data.RxBuffer[Data.RxCount++]=USART_ReceiveData(USART1); //Data.RxCount &= 0xFF; } if (Data.RxBuffer[Data.RxCount - 1] == 0xEA) Data.RxHeader = Data.RxCount - 1; if(Data.RxBuffer[Data.RxHeader]==0xEA&&Data.RxBuffer[Data.RxCount -1] == 0x55) { Data.RxLen = Data.RxCount-1-Data.RxHeader; Data.RxOK = 1; } if(USART_GetFlagStatus(USART1, USART_IT_ORE) == SET) { USART_ClearFlag(USART1, USART_IT_ORE); USART_ReceiveData(USART1); } }
3. 文件3——stm32f10x_conf.h #ifndef __STM32F10x_CONF_H #define __STM32F10x_CONF_H #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" #include"stm32f10x_usart.h" #include "misc.h" #endif /* __STM32F10x_CONF_H */
4. 文件4——main.c #include "UserDefine.h" RxTxBuffer_t Data; int main(void) { u8 kcnt = 0; u8 cmd1, cmd2; SystemInit(); GPIO_Configure(); USART_Configure(); NVIC_Configure(); EmptyRxBuffer(BufferMAX); SendString((u8 *)("Welcome to my STM32!!!\n")); while (true) { if (Data.RxOK) { cmd1 = Data.RxBuffer[Data.RxHeader + 1]; cmd2 = Data.RxBuffer[Data.RxHeader + 2]; switch (cmd1) { case 0x01: LED_ON; Data.RxOK = 0; Data.RxCount = 0; EmptyRxBuffer(BufferMAX); break; case 0x02: LED_OFF; Data.RxOK = 0; Data.RxCount = 0; EmptyRxBuffer(BufferMAX); break; } } } }
5. 文件5——UserDefine.h #ifndef __USERDEFINE_H__ #define __USERDEFINE_H__ #include <stm32f10x.h> #include <stdbool.h> #include <string.h> #include <stdio.h> #define BufferMAX 255 #define LED_ON GPIO_ResetBits(GPIOB, GPIO_Pin_12) #define LED_OFF GPIO_SetBits(GPIOB, GPIO_Pin_12) typedef struct { u8 RxBuffer[BufferMAX]; u8 TxBuffer[BufferMAX]; vu8 RxCount; vu8 TxCount; vu8 RxHeader; vu8 RxOK; vu8 RxLen; } RxTxBuffer_t; typedef enum { ERR = 0, OK = !ERR } RxTxState_t; void GPIO_Configure(); void USART_Configure(); void NVIC_Configure(); void DelayNms(u16 time); RxTxState_t SendOneByte(u8 dat); void SendString(u8 *Message); void EmptyRxBuffer(u8 len); #endif /* __USERDEFINE_H__ */
6. 文件6——User.c #include "UserDefine.h" extern RxTxBuffer_t Data; void GPIO_Configure() { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_ResetBits(GPIOB, GPIO_Pin_12); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2P eriph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); } void USART_Configure() { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_HardwareFlowControl=USART_ HardwareFlowControl_None; USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode _Tx; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_WordLength=USART_WordLength _8b; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); } void NVIC_Configure() { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); } void DelayNms(u16 time) { u16 i = 0; while (time--) { i = 12000; while (i--) ; } } RxTxState_t SendOneByte(u8 dat) { vu32 cnt = 0; USART_SendData(USART1, dat); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)== RESET) { cnt++; if (cnt == 100000) return ERR; } return OK; } void SendString(u8 *Message) { while (*Message != '\0') SendOneByte(*Message++); } void EmptyRxBuffer(u8 len) { u8 i; for(i = 0; i < len; i++) Data.RxBuffer = 0; }
如有错误,欢迎指出讨论 如果感兴趣的的话,也欢迎关注我们的公众号,我们会定期更新一些技术类文章
|