这是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加油!
stm32串口实验:stm32通过usart1进行串口收发,PA9(TX)和PA10(RX)
原文:https://www.cnblogs.com/hjf-log/p/stm32-usart1.html