第一次深入学习stm32,花了好长时间才看懂代码(主要是C语言学习不够深入),又花了段时间自己敲了一遍,然后比对教程,了解了利用中断来串口通信的设置方法。
板子是探索版f407,本实验工程把正点原子库函数工程模版拿来使用,自己主要敲了一下main.c、usart.h和.c文件。
一、头文件usart.h
1 #ifndef __USART_H //定义同时防止重复定义 2 #define __USART_H 3 4 #include "stdio.h" 5 #include "stm32f4xx_conf.h" 6 #include "sys.h" 7 8 #define USART_REC_LEN 200 //最大接收字节数 9 #define EN_USART1_RX 1 //(1)使能串口接收 10 11 12 /*extern外部声明引用这个变量,在.c文件寻找。*/ 13 extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大字节为USART_REC_LEN,末字符为换行符 14 extern u16 USART_RX_STA; //接收状态标记 15 void uart_init(u32 bound); //.c文件里面的函数声明 16 17 #endif
头文件主要是其他文件需要用到的一些参数()的宏定义及声明,加.c文件的函数
二、usart.c文件
1、所需要的头文件
2、定义参数并且使能串口接收
3、uart_init(u32 bound) //主函数调用设置波特率
参数结构:GPIO/USART/NVIC.InitSturcture
a,使能GPIOA和USART1时钟,它们分别挂在在AHB1和APB2。
b,GPIOA的PA9和PA10复用为USART1。
c,串口1复用对应的IO口设置
d,串口1初始化设置(波特率、字长、停止位、奇偶、硬件流、模式)
e,使能串口1USART_Cmd(x,x)
f,宏定义
#if 条件
USART_ITConfig( )开启中断
设置中断通道、优先级、子优先级、IRQ使能
初始化NVIC_Init( )
4、串口1中断服务函数(当一个字节数据接收到,会触发中断,该函数处理中断)
USART_IRQHandler()
参数USART_RX_STA是上一次累计的字节接收量,Res是这一次接收的一个字节数据
1 #include "sys.h" 2 #include "usart.h" 3 4 //加入以下代码,支持printf函数,而不需要选择use MicroLIB 5 #if 1 6 #pragma import(__use_no_semihosting) 7 //标准库需要的支持函数 8 struct __FILE 9 { 10 int handle; 11 }; 12 13 FILE __stdout; 14 //定义_sys_exit()以避免使用半主机模式 15 _sys_exit(int x) 16 { 17 x = x; 18 } 19 //重定义fputc函数 20 int fputc(int ch, FILE *f) 21 { 22 while((USART1->SR&0X40)==0);//循环发送,直到发送完毕 23 USART1->DR = (u8) ch; 24 return ch; 25 } 26 #endif 27 28 #if EN_USART1_RX 29 u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大字节为USART_REC_LEN,末字符为换行符 30 u16 USART_RX_STA=0; //接收状态标记初始化为0 31 32 33 34 void uart_init(u32 bound) 35 { 36 GPIO_InitTypeDef GPIO_InitStructure; 37 USART_InitTypeDef USART_InitStructure; 38 NVIC_InitTypeDef NVIC_InitStructure; 39 40 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能gpioa的时钟 41 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟 42 43 GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);//复用为USART1 44 GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);//复用为USART1 45 46 //串口1复用对应的 47 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; 48 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 49 GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz; 50 GPIO_InitStructure.GPIO_OType =GPIO_OType_PP;//复用推挽 51 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 52 GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化 53 54 USART_InitStructure.USART_BaudRate=bound;//设置波特率 55 USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长 56 USART_InitStructure.USART_StopBits=USART_StopBits_1;//停止位 57 USART_InitStructure.USART_Parity=USART_Parity_No;//无奇偶校验 58 USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//发送接收模式 59 USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//无硬件流控制 60 USART_Init(USART1, &USART_InitStructure);//初始化串口 61 62 USART_Cmd(USART1,ENABLE);//使能串口1 63 64 #if EN_USART1_RX //开启串口接收相关的中断 65 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); 66 67 NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//串口1中断通道 68 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能中断通道 69 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; 70 NVIC_InitStructure.NVIC_IRQChannelSubPriority=3; 71 72 NVIC_Init(&NVIC_InitStructure); 73 74 #endif 75 76 } 77 78 /*串口1中断服务函数,接收到一个数据就产生一次中断,当接收到两次数据为0X0D和OXOA时, 79 USART_RX_STA最高位置1,此时main函数while循环执行。*/ 80 81 void USART1_IRQHandler(void) 82 { 83 u8 Res; 84 if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)//接收中断 85 { 86 Res=USART_ReceiveData(USART1); 87 if((USART_RX_STA&0x8000)==0) 88 { 89 if(USART_RX_STA&0x4000) 90 { 91 if(Res==0x0a) 92 { 93 USART_RX_STA|=0x8000;//将bit15位置1,此时main函数while循环里面的判断生效。 94 } 95 else 96 { 97 USART_RX_STA=0;//上一次标志位bit14置1,此次数据不为0x0a,说明输入错误,只有整段数据末尾为0x0d,0x0a数据才有效。 98 } 99 } 100 else 101 { 102 if(Res==0x0d) 103 { 104 USART_RX_STA|=0x4000;}//这次数据为0x0d,将bit14位置1。 105 else 106 { 107 USART_RX_STA++; 108 USART_RX_BUF[USART_RX_STA]=Res; 109 110 if(USART_RX_STA >USART_REC_LEN-1) //如果接收到的长度大于规定的长度,说明发送错误,状态清零。 111 USART_RX_STA=0; 112 } 113 } 114 } 115 } 116 } 117 #endif
三、main.c
头文件
定义参数t,len(发送长度),times(时间参数)
设置系统中断优先级分组2
初始化延时、串口(波特率)
while(1)
{
if判断USART_RX_STA的Bit15位是否 为1,若是意味发送完成。
{
数据长度赋给len
for(0;t { 将USART_RX_BUF[t]数组一个个通过串口1发送回数据 whilewhile(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);一直轮询,直到当前数据发送完 } 当所有数据发送完成后,USART_RX_STA置0 } else 打印提示内容 } 其中 USART_GetFlagStatus(main.c用到)和USART_GetITStatus(usart.c用到),敲代码容易弄混, USART_GetFlagStatus是在没有使能相应的中断函数时,通常使用该函数来判断标志位是否置位。 USART_GetITStatus则相反,参考关于STM32的USART_GetFlagStatus和USART_GetITStatus解析(异步通信) - CSDN博客 1 #include"stm32f4xx.h"
2 #include "usart.h"
3 #include "delay.h"
4 #include "sys.h"
5
6
7 int main()
8 {
9 u8 t;
10 u8 len=0;
11 u16 times;
12 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组2
13 delay_init(168);
14 uart_init(115200);
15
16 while(1)
17 {
18
19 if(USART_RX_STA&0x8000)
20 {
21 printf("\r\n您打印的消息为:\r\n");
22 len = USART_RX_STA&0x3fff; //接收到此次接收到的数据长度
23 for(t=0;t