基于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
1.png (85.86 KB, 下載次數: 92)
下載附件
2019-1-31 18:20 上傳
2. 修改晶振頻率為8.0
2.png (75.42 KB, 下載次數: 91)
下載附件
2019-1-31 18:34 上傳
STM32F103C8的內部晶振頻率為8MHz。 3. 設置預處理宏定義符號:USE_STDPERIPH_DRIVER,STM32F10X_MD
3.png (81.13 KB, 下載次數: 80)
下載附件
2019-1-31 18:34 上傳
USE_STDPERIPH_DRIVER表示要使用固件庫,STM32F10X_MD表示選用的是中等容量的STM32芯片。 4. 設置IncludePath路徑
4.png (96.94 KB, 下載次數: 93)
下載附件
2019-1-31 18:35 上傳
該項配置是為了將STM32的啟動文件及官方庫包含進項目中,這樣能加快開發速度,而且使用官方庫開發相較于其他方式而言更淺顯易懂。 5. 設置調試方式
5.png (85.16 KB, 下載次數: 79)
下載附件
2019-1-31 18:36 上傳
此項為PC與STM32芯片的連接方式,具體請自行調整 6. 設置啟動方式
6.png (76.35 KB, 下載次數: 88)
下載附件
2019-1-31 18:36 上傳
此項設置為程序下載后及啟動,免去了手動啟動的環節。 四、源程序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; }
如有錯誤,歡迎指出討論 如果感興趣的的話,也歡迎關注我們的公眾號,我們會定期更新一些技術類文章
qrcode_for_gh_4475599e75b5_258.jpg (27.85 KB, 下載次數: 108)
下載附件
2019-1-31 18:15 上傳
|