這是stm32開發中比較簡單的實驗,原理是通過串口助手發送信息,stm32接收到信息以后在串口助手中打印相同的內容。
這里直接分享keil5工程代碼,是在工程模板的基礎上移植和修改了正點原子的串口代碼
百度網盤鏈接:https://pan.baidu.com/s/1aptEjcYPuQlDD_ayZaNoJw
提取碼:8hr9
(如果失效的話可以在下方評論留下郵箱,我看到會給你發一份)
順便把usart.c和usart.h還有mian.c中的代碼復制到下面,小伙伴可以直接移植到自己的工程中
實現的效果也在下面放上串口助手中顯示的圖片
usart.c
1 #include "sys.h" 2 #include "usart.h" 3 4 5 //STM32F103核心板例程 6 //庫函數版本例程 7 /********** mcudev.taobao.com 出品 ********/ 8 9 10 ////////////////////////////////////////////////////////////////////////////////// 11 //如果使用ucos,則包括下面的頭文件即可. 12 #if SYSTEM_SUPPORT_UCOS 13 #include "includes.h" //ucos 使用 14 #endif 15 ////////////////////////////////////////////////////////////////////////////////// 16 //STM32開發板 17 //串口1初始化 18 19 ////////////////////////////////////////////////////////////////////////////////// 20 21 22 ////////////////////////////////////////////////////////////////// 23 //加入以下代碼,支持printf函數,而不需要選擇use MicroLIB 24 #if 1 25 #pragma import(__use_no_semihosting) 26 //標准庫需要的支持函數 27 struct __FILE 28 { 29 int handle; 30 31 }; 32 33 FILE __stdout; 34 //定義_sys_exit()以避免使用半主機模式 35 void _sys_exit(int x) 36 { 37 x = x; 38 } 39 //重定義fputc函數 40 int fputc(int ch, FILE *f) 41 { 42 while((USART1->SR&0X40)==0);//循環發送,直到發送完畢 43 USART1->DR = (u8) ch; 44 return ch; 45 } 46 #endif 47 48 /*使用microLib的方法*/ 49 /* 50 int fputc(int ch, FILE *f) 51 { 52 USART_SendData(USART1, (uint8_t) ch); 53 54 while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} 55 56 return ch; 57 } 58 int GetKey (void) { 59 60 while (!(USART1->SR & USART_FLAG_RXNE)); 61 62 return ((int)(USART1->DR & 0x1FF)); 63 } 64 */ 65 66 #if EN_USART1_RX //如果使能了接收 67 //串口1中斷服務程序 68 //注意,讀取USARTx->SR能避免莫名其妙的錯誤 69 u8 USART_RX_BUF[USART_REC_LEN]; //接收緩沖,最大USART_REC_LEN個字節. 70 //接收狀態 71 //bit15, 接收完成標志 72 //bit14, 接收到0x0d 73 //bit13~0, 接收到的有效字節數目 74 u16 USART_RX_STA=0; //接收狀態標記 75 76 void uart_init(u32 bound){ 77 //GPIO端口設置 78 GPIO_InitTypeDef GPIO_InitStructure; 79 USART_InitTypeDef USART_InitStructure; 80 NVIC_InitTypeDef NVIC_InitStructure; 81 82 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA時鍾 83 //USART1_TX PA.9 84 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 85 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 86 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽輸出 87 GPIO_Init(GPIOA, &GPIO_InitStructure); 88 89 //USART1_RX PA.10 90 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 91 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入 92 GPIO_Init(GPIOA, &GPIO_InitStructure); 93 94 //Usart1 NVIC 配置 95 96 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; 97 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//搶占優先級3 98 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優先級3 99 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 100 NVIC_Init(&NVIC_InitStructure); //根據指定的參數初始化VIC寄存器 101 102 //USART 初始化設置 103 104 USART_InitStructure.USART_BaudRate = bound;//一般設置為9600; 105 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8位數據格式 106 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位 107 USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗位 108 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數據流控制 109 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發模式 110 111 USART_Init(USART1, &USART_InitStructure); //初始化串口 112 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟中斷 113 USART_Cmd(USART1, ENABLE); //使能串口 114 115 } 116 117 118 119 void USART1_IRQHandler(void) //串口1中斷服務程序 120 { 121 u8 Res; 122 #ifdef OS_TICKS_PER_SEC //如果時鍾節拍數定義了,說明要使用ucosII了. 123 OSIntEnter(); 124 #endif 125 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中斷(接收到的數據必須是0x0d 0x0a結尾) 126 { 127 Res =USART_ReceiveData(USART1);//(USART1->DR); //讀取接收到的數據 128 129 if((USART_RX_STA&0x8000)==0)//接收未完成 130 { 131 if(USART_RX_STA&0x4000)//接收到了0x0d 132 { 133 if(Res!=0x0a)USART_RX_STA=0;//接收錯誤,重新開始 134 else USART_RX_STA|=0x8000; //接收完成了 135 } 136 else //還沒收到0X0D 137 { 138 if(Res==0x0d)USART_RX_STA|=0x4000; 139 else 140 { 141 USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; 142 USART_RX_STA++; 143 if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收數據錯誤,重新開始接收 144 } 145 } 146 } 147 } 148 #ifdef OS_TICKS_PER_SEC //如果時鍾節拍數定義了,說明要使用ucosII了. 149 OSIntExit(); 150 #endif 151 } 152 #endif
usart.h
1 #ifndef __USART_H 2 #define __USART_H 3 #include "stdio.h" 4 #include "sys.h" 5 6 //STM32F103核心板例程 7 //庫函數版本例程 8 /********** mcudev.taobao.com 出品 ********/ 9 10 ////////////////////////////////////////////////////////////////////////////////// 11 //STM32開發板 12 //串口1初始化 13 14 #define USART_REC_LEN 200 //定義最大接收字節數 200 15 #define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收 16 17 extern u8 USART_RX_BUF[USART_REC_LEN]; //接收緩沖,最大USART_REC_LEN個字節.末字節為換行符 18 extern u16 USART_RX_STA; //接收狀態標記 19 //如果想串口中斷接收,請不要注釋以下宏定義 20 void uart_init(u32 bound); 21 #endif
main.c
1 #include "sys.h" 2 #include "delay.h" 3 #include "usart.h" 4 5 uint8_t t; 6 uint8_t len; 7 uint16_t times=0; 8 9 int main(void) 10 { 11 delay_init(); //延時函數初始化 12 uart_init(115200); //串口初始化為115200 13 14 while(1) 15 { 16 if(USART_RX_STA&0x8000) //USART_RX_STA第十六位為1則括號內為1,表示接收完數據 17 { 18 len=USART_RX_STA&0x3fff;//得到此次接收到的數據長度 19 printf("\r\n您發送的消息為:\r\n\r\n"); 20 for(t=0;t<len;t++) 21 { 22 USART_SendData(USART1, USART_RX_BUF[t]);//向串口1發送數據 23 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待發送結束 24 } 25 printf("\r\n\r\n");//插入換行 26 USART_RX_STA=0; 27 }else 28 { 29 times++; 30 if(times%500==0)printf("請輸入數據,以回車鍵結束\n"); 31 delay_ms(10); 32 } 33 } 34 }
串口實驗效果圖:
未發送時
發送數據時:
祝小伙伴們2020加油!