STM32F407 您所在的位置:网站首页 如何进行串口调试 STM32F407

STM32F407

2024-07-07 12:52| 来源: 网络整理| 查看: 265

STM32F407——串口通信

文章目录 STM32F407——串口通信前言一、串口通信的概念及分类1、串口及串口通信概念2、串口分类 二、串口配置与调试1、配置步骤2、串口收发功能测试 结语

前言

本文将对串口通信的分类和基于 stm32 的串口配置进行介绍,以及如何使用串口调试助手进行串口收发功能的调试,旨在帮助还不会使用 stm32 单片机串口资源进行通信的家人们快速学会如何使用串口来进行通信。 (纯干货、快速上手、零基础也能会!!!)

一、串口通信的概念及分类 1、串口及串口通信概念

(1)串口,即串行接口,是一种可以将接收来自CPU的并行数据字符转换为连续的串行数据流发送出去,同时可将接收的串行数据流转换为并行的数据字符供给CPU的器件。

(2)串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。

2、串口分类

常用的有串口有三种: (1)RS232标准的串口 这一类的串口采用的是 RS232 电平标准,其中高电平为 +15V ,低电平为 -15V ,这类串口抗干扰性强,但是对我这种平平无奇大学生来说用不上。就是下面这玩意: 在这里插入图片描述 在这里插入图片描述

(2)USB转串口 这类串口十分常用,主要用来调试串口(下面会将如何用)。在 STM32F407 中也有一个 USB 串口,如下图所示: 在这里插入图片描述 板载 CH340 USB 转 TTL 芯片,可以说是个串口调试的工具。 (3)原生的串口 这一类主要用于控制器跟串口的设备或者传感器通信,不需要经过电平转换芯片来转换电平,直接就用 TTL 电平(高电平 3.3V 或 5V,低电平 0V)通信。大家平常用的蓝牙、传感器等很多都是采用这个。

二、串口配置与调试 1、配置步骤

以 STM32F407 的串口3为例,跟大家讲下如何配置一个串口,使其能进行数据收发。 (1)串口初始化 在这一步中,需要: ① 对该串口使用到的 IO 口进行初始化和使能相应的时钟树,并对端口进行复用映射; ② 中断配置 (主要是一个优先级); ③ 串口初始化配置(奇偶校验、收发配置等); ④ 串口使能; 按上述步骤编写函数,代码如下:

void USART3_Init(u32 bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //使能GPIOB时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//使能USART3时钟 //串口3对应引脚复用映射 GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_USART3); GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_USART3); //USART3端口配置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOB,&GPIO_InitStructure); //Usart3 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 //USART3 初始化设置 USART_InitStructure.USART_BaudRate = bound;//串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART3, &USART_InitStructure); //初始化串口3 USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断 USART_Cmd(USART3, ENABLE); //使能串口3 TIM7_Int_Init(100-1,8400-1); //10ms中断一次 USART3_RX_STA=0; //清零 TIM_Cmd(TIM7,DISABLE); //关闭定时器7 }

(2)编写发送与接收函数 这个其实不用编写,库里就有了,接收与发送分别是:

uint16_t USART_ReceiveData(USART_TypeDef* USARTx) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); /* Receive Data */ return (uint16_t)(USARTx->DR & (uint16_t)0x01FF); } void USART_SendData(USART_TypeDef* USARTx, uint16_t Data) { /* Check the parameters */ assert_param(IS_USART_ALL_PERIPH(USARTx)); assert_param(IS_USART_DATA(Data)); /* Transmit Data */ USARTx->DR = (Data & (uint16_t)0x01FF); }

这个大家知道一下这两个的功能和如何调用函数即可。如果要接收串口3的信息,这样调用:Receive = USART_ReceiveData(USART3);如果要通过串口3发送消息,则:USART_SendData(USART3,data)。等下在中断函数和串口打印函数中会用到。 (3)编写中断服务函数

void USART3_IRQHandler(void) //串口1中断服务程序 { #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS. OSIntEnter(); #endif if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾) { Res =USART_ReceiveData(USART3);//(USART3->DR); //读取接收到的数据 if((USART3_RX_STA&0x8000)==0)//接收未完成 { if(USART3_RX_STA&0x4000)//接收到了0x0d { if(Res!=0x0a)USART3_RX_STA=0;//接收错误,重新开始 else USART3_RX_STA|=0x8000; //接收完成了 } else //还没收到0X0D { if(Res==0x0d)USART3_RX_STA|=0x4000; else { USART3_RX_BUF[USART3_RX_STA&0X3FFF]=Res ; USART3_RX_STA++; if(USART3_RX_STA>(USART3_MAX_RECV_LEN-1))USART3_RX_STA=0;//接收数据错误,重新开始接收 } } } } }

中断函数是在发生中断时间后,主程序自动进入中断函数运行,运行结束后在退出中断函数,返回到进入中断函数之前的运行状态。我愿把他成为一个时光静止器,执行到这个函数时,外界暂停,此刻整个世界只有自己,我们可以利用这段时间尽情地做我们想做的事,对我们所接收的信息进行分析处理等等。 (4)编写串口打印函数 这一函数与 C 语言中的 printf 其实是类似的,可将接收到的信息打印到电脑上,主要用于调试,函数如下:

//串口3,printf 函数 //确保一次发送数据不超过USART3_MAX_SEND_LEN字节 void u3_printf(char* fmt,...) { u16 i,j; va_list ap; va_start(ap,fmt); vsprintf((char*)USART3_TX_BUF,fmt,ap); va_end(ap); i=strlen((const char*)USART3_TX_BUF); //此次发送数据的长度 for(j=0;j //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //使能GPIOC时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);//使能USART4时钟 //串口1对应引脚复用映射 GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_UART4); //GPIOC11复用为UART4 GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_UART4); //GPIOC10复用为UART4 //USART1端口配置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_10; //GPIOC11和GPIOC10初始化 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOB11,和GPIOB10 //USART1 初始化设置 USART_InitStructure.USART_BaudRate = bound;//波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(UART4, &USART_InitStructure); //初始化串口4 USART_Cmd(UART4, ENABLE); //使能串口4 //USART_ClearFlag(USART1, USART_FLAG_TC); USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);//开启中断 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 } void UART4_IRQHandler(void) //串口4中断服务程序 { u8 Res; if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾) { Res =USART_ReceiveData(UART4);//(USART1->DR); //读取接收到的数据 if((UART4_RX_STA&0x8000)==0)//接收未完成 { if(UART4_RX_STA&0x4000)//接收到了0x0d { if(Res!=0x0a)UART4_RX_STA=0;//接收错误,重新开始 else UART4_RX_STA|=0x8000; //接收完成了 } else //还没收到0X0D { if(Res==0x0d)UART4_RX_STA|=0x4000; else { UART4_RX_BUF[UART4_RX_STA&0X3FFF]=Res ; UART4_RX_STA++; if(UART4_RX_STA>(UART4_MAX_RECV_LEN-1))UART4_RX_STA=0;//接收数据错误,重新开始接收 } } } } } void u4_printf(char* fmt,...) { u16 i,j; va_list ap; va_start(ap,fmt); vsprintf((char*)UART4_TX_BUF,fmt,ap); va_end(ap); i=strlen((const char*)UART4_TX_BUF);//此次发送数据的长度 for(j=0;j


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有