stm32串口通信实验,一点笔记

第一次深入学习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

  打印提示内容

}

 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)
24             {
25             USART_SendData(USART1,USART_RX_BUF[t]); //将单片机接收到的数据发送回电脑
26             while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);  //获取发送的状态,轮询直到这一条数据发送成功
27             }
28             printf("\r\n\r\n");  //插入换行
29             USART_RX_STA =0;
30         }
31 else
32         {
33             times++;
34             if(times%5000==0)
35             {
36                 printf("\r\nALIENTEK 探索者STM32F407开发板 串口实验\r\n");
37               38             }
39             if(times%200==0)printf("请输入数据,以回车键结束\r\n");  
40             delay_ms(10);   
41         }
42     }
43 }

其中

USART_GetFlagStatus(main.c用到)和USART_GetITStatus(usart.c用到),敲代码容易弄混,

USART_GetFlagStatus是在没有使能相应的中断函数时,通常使用该函数来判断标志位是否置位。

USART_GetITStatus则相反,参考关于STM32的USART_GetFlagStatus和USART_GetITStatus解析(异步通信) - CSDN博客 

转载于:https://www.cnblogs.com/yuege21/p/9607738.html

你可能感兴趣的:(stm32串口通信实验,一点笔记)