STM32F4VGT6-DISCOVERY:uart1驱动

对于这款板子,官方并没有提供串口例程,只能自行添加。

一、PA9/PA10复用成串口1功能不可用

驱动测试代码如下:

main.c:

#include "main.h"
#include <stdio.h>

void usart1_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    //(1)串口时钟和 GPIO 时钟使能
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//GPIO口时钟使能, 引脚PA9,PA10可以复用为串口功能
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口UART1时钟使能, 串口1是挂载在 APB2总线下的外设

    //(2)配置GPIO引脚为复用功能[PA9+PA10]
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//电平翻转速度100MHz
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽复用输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
    GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化 PA9,PA10

    //(3)配置串口1参数
    USART_InitStructure.USART_BaudRate = 115200;//波特率
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不使用硬件流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
    USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8个数据位
    USART_Init(USART1, &USART_InitStructure); //初始化串口1

    //(4) 开启中断并且初始化 NVIC,使能相应中断[接收一个byte触发中断一次]
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级 3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//响应优先级 3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器

    //(5) 使能串口1
    USART_Cmd(USART1, ENABLE);
}

//串口1中断服务函数
void USART1_IRQHandler(void)
{
    char res;
    //检查标志位
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        res = USART_ReceiveData(USART1);//收到数据后读出来
        USART_SendData(USART1,res);//读到数据后立刻发送出去
        //清空标志位
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }
}

int main(void)
{
    usart1_init();
    while(1)
    {
        ;
    }

    return 0;
}

固件烧录后,连接PC端串口工具,串口收发功能不可用。原因:PA9/PA10设计给板载USB使用,打开原理如下:

所以,只能换一组GPIO,换成PB6/PB7(原理图上可确认没有其他外设使用),测试代码如下:

#if 0
void usart1_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	//(1)串口时钟和 GPIO 时钟使能
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//GPIO口时钟使能, 引脚PA9,PA10可以复用为串口功能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口UART1时钟使能, 串口1是挂载在 APB2总线下的外设

	//(2)配置GPIO引脚为复用功能[PA9+PA10]
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//电平翻转速度100MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化 PA9,PA10

	//(3)配置串口1参数
	USART_InitStructure.USART_BaudRate = 115200;//波特率
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不使用硬件流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8个数据位
	USART_Init(USART1, &USART_InitStructure); //初始化串口1

	//(4) 开启中断并且初始化 NVIC,使能相应中断[接收一个byte触发中断一次]
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级 3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//响应优先级 3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化NVIC寄存器

	//(5) 使能串口1
	USART_Cmd(USART1, ENABLE);
}

//串口1中断服务函数
void USART1_IRQHandler(void)
{
	char res;
	//检查标志位
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{
		res = USART_ReceiveData(USART1);//收到数据后读出来
		USART_SendData(USART1,res);//读到数据后立刻发送出去

		//清空标志位
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}

#else
void usart1_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	//(1)串口时钟和 GPIO 时钟使能
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //使能GPIOB时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口UART1时钟使能, 串口1是挂载在 APB2总线下的外设

	//(2)配置GPIO引脚为复用功能[PB6+PB7]
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//电平翻转速度100MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化 PA9,PA10

	//(3)配置串口1参数
	USART_InitStructure.USART_BaudRate = 115200;//波特率
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不使用硬件流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8个数据位
	USART_Init(USART1, &USART_InitStructure); //初始化串口1

	//(4) 开启中断并且初始化 NVIC,使能相应中断[接收一个byte触发中断一次]
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级 3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//响应优先级 3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化NVIC寄存器

	//(5) 使能串口1
	USART_Cmd(USART1, ENABLE);
}

//串口1中断服务函数
void USART1_IRQHandler(void)
{
	char res;
	STM_EVAL_LEDOn(LED4);

	//检查标志位
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{
		res = USART_ReceiveData(USART1);//收到数据后读出来
		STM_EVAL_LEDOn(LED5);
		USART_SendData(USART1,res);//读到数据后立刻发送出去

		//清空标志位
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}
#endif

int main(void)
{
	usart1_init();
	while(1)
	{
		;
	}

	return 0;
}

板子实物图连接如下:

串口工具测试如下:

二、串口标准输入输出重定向打印实现

直接重写标准输入输出函数的底层接口即可,如下:

//重写printf底层函数接口

int fputc(int c, FILE *stream)

{

  USART1->DR=c; //发送一个字符

  while(!(USART1->SR&1<<7)){}

return c;

}

//重写scanf底层函数接口

int fgetc(FILE *stream)

{

  while(!(USART1->SR&1<<5)){}

    return USART1->DR;

}

烧录固件,并按reset键,观察串口调试助手上的打印:使用ST-LINK的方式进行烧录

串口助手:

三、完整代码

usart.c

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include <stdio.h>

void usart1_init(uint32_t BaudRate)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	//(1)串口时钟和 GPIO 时钟使能
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //使能GPIOB时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//串口UART1时钟使能, 串口1是挂载在 APB2总线下的外设

	//(2)配置GPIO引脚为复用功能[PB6+PB7]
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//电平翻转速度100MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化 PA9,PA10

	//(3)配置串口1参数
	USART_InitStructure.USART_BaudRate = BaudRate;//波特率
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不使用硬件流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8个数据位
	USART_Init(USART1, &USART_InitStructure); //初始化串口1

	//(4) 开启中断并且初始化 NVIC,使能相应中断[接收一个byte触发中断一次]
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级 3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//响应优先级 3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化NVIC寄存器

	//(5) 使能串口1
	USART_Cmd(USART1, ENABLE);
}

//串口1中断服务函数
void USART1_IRQHandler(void)
{
	char res;

	//检查标志位
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{
		res = USART_ReceiveData(USART1);//收到数据后读出来

		USART_SendData(USART1,res);//读到数据后立刻发送出去

		//清空标志位
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}

//重写printf底层函数接口
int fputc(int c, FILE *stream)
{
	  USART1->DR=c; //发送一个字符
	  while(!(USART1->SR&1<<7)){}
		return c;
}

//重写scanf底层函数接口
int fgetc(FILE *stream)
{
	while(!(USART1->SR&1<<5)){}
    return USART1->DR;
}

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

usart.h

#ifndef __USART__H__
#define __USART__H__

void usart1_init(uint32_t BaudRate);

#endif /* __USART__H__ */

main.c

#include "usart.h"
#include <stdio.h>

int main(void)
{
	usart1_init(115200);
	printf("hello world!\n");
	while(1)
	{
		;
	}

	return 0;
}

注:这款Discovery开发板是基于标准外设库函数来开发的,因此工程中要把串口相关的库函数文件添加进来,如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/108577.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端 : 用html ,css,js写一个你画我猜的游戏

1.HTML&#xff1a; <body><div id "content"><div id "box1">计时器</div><div id"box"><div id "top"><div id "box-top-left">第几题:</div><div id "box…

linux-磁盘应用

目录 一、磁盘内容简述 1、一些基本概念 2、分区简述 3、常见文件系统 4、linux硬盘文件 二、对linux系统进行分区 1、用fdisk进行分区 2、用parted进行分区 一、磁盘内容简述 1、一些基本概念 - 扇区大小&#xff1a;512Btyes&#xff0c;0.5KB - 磁盘最小存储单位&…

小黑子—spring:第一章 Bean基础

spring入门1.0 一 小黑子对spring基础进行概述1.1 spring导论1.2 传统Javaweb开发困惑及解决方法1.3 三大的思想提出1.3.1 IOC入门案例1.3.2 DI入门案例 1.4 框架概念1.5 初识spring1.5.1 Spring Framework 1.6 BeanFactory快速入门1.7 ApplicationContext快速入门1.8 BeanFact…

python之计算平面点集的的面积

在当今数据驱动的世界中&#xff0c;计算平面点集的最小外接轮廓面积被广泛应用于各种实际场景中。它是一项重要而魅力十足的任务&#xff0c;旨在找到一个最小的矩形或多边形区域&#xff0c;能够完全包围给定的离散点集。这个看似简单的问题背后隐藏着许多挑战&#xff0c;需…

HTML5+CSS3+Vue小实例:路飞出海的动画特效

实例:路飞出海的动画特效 技术栈:HTML+CSS+Vue 效果: 源码: 【HTML】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content=&…

windows下OOM排查

如下有一段代码 package com.lm.demo.arthas.controller;import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import java.util.A…

车载音频项目

加我微信hezkz17进数字音频系统研究开发交流答疑群(课题组) ー 1&#xff0e;负责此项目的音频链路的设计及其实现 在ADSP21375上实现音频链路的处理。如噪声门&#xff0c;压限器&#xff0c;高低通&#xff0c;PEQ、各种效果等。 2&#xff0e;负责DSP与MCU端SPI协议实现。M…

Python文件——使用Python读取txt文件

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 本文专栏&#xff1a;Python专栏 专栏介绍&#xff1a;本专栏为免费专栏&#xff0c;并且会持续更新python基础知识&#xff0c;欢迎各位订阅关注. 目录 一、文件的编码 1. 什么是编码 2. 常见的编码 二、P…

【纯离线】Ubuntu离线安装ntp时间同步服务

Ubuntu离线安装ntp服务 准备阶段&#xff1a;下载安装包 apt-get download ntp apt-get download ntpdate 一、服务端( 192.166.6.xx) 1、环境准备 先判断是否已安装 systemd-timesyncd systemctl is-active systemd-timesyncd 如果返回结果是 active&#xff0c;则表示…

文件夹批量改名:如何在文件夹名左边添加递增的自动编号

在文件管理的过程中&#xff0c;我们有时需要对文件夹进行重命名&#xff0c;使其更具区分度和可读性。为了实现这一目标&#xff0c;我们可以采用在文件夹名左边添加递增的自动编号的方法。本文将介绍云炫文件管理器如何进行文件夹批量改名&#xff0c;以在文件夹名左边添加递…

mathtype7.4破解永久激活码

MathType(数学公式编辑器)是由Design Science公司研发的一款专业的数学公式编辑工具。MathType功能非常强大&#xff0c;尤其适用于专门研究数学领域的人群使用。使用MathType让你在输入数学公式的时候能够更加的得心应手&#xff0c;各种复杂的运算符号也不在话下。 MathType最…

Vue3.0插槽

用法&#xff1a; 父组件App.vue <template><div><!--将html代码插入到子组件中带默认名称的插槽中--><AChild><!--这段html会插入到AChild组件中<slot></slot>插槽中--><!-- 注意&#xff1a;写在父组件中的html代码只能在父组…

百度网盘使用指南

文章目录 备份篇手机文件备份电脑文件备份 查找篇移动端PC端 文件操作文件解压文件扫描PDF工具图片工具音频操作 备份篇 手机文件备份 在百度网盘APP种点击 我的–设置–自动备份设置 里边有相册备份, 文档备份, 微信文件备份, 手机通讯录, 短信, 通话备份等功能 电脑文件备…

目标检测类项目数据集汇总

一、玩手机数据集及检测 玩手机数据集下载地址分享: https://download.csdn.net/download/qq_34717531/19870205 二、狗的数据集及检测 狗目标检测数据集下载地址分享:https://download.csdn.net/download/qq_34717531/20813390 三、猫数据集及检测 猫数据集下载地址分享: ht…

回归算法|长短期记忆网络LSTM及其优化实现

本期文章将介绍LSTM的原理及其优化实现 序列数据有一个特点&#xff0c;即“没有曾经的过去则不存在当前的现状”&#xff0c;这类数据以时间为纽带&#xff0c;将无数个历史事件串联&#xff0c;构成了当前状态&#xff0c;这种时间构筑起来的事件前后依赖关系称其为时间依赖&…

c++设计模式三:工厂模式

本文通过一个例子简单介绍简单工厂模式、工厂模式和抽象工厂模式。 1.简单工厂&#xff08;静态&#xff09; 假如我想换个手机&#xff0c;换什么手机呢&#xff1f;可以考虑苹果或者华为手机&#xff0c;那我们用简单工厂模式来实现这个功能&#xff1a; 我们关注的产品是手…

基于群居蜘蛛算法的无人机航迹规划

基于群居蜘蛛算法的无人机航迹规划 文章目录 基于群居蜘蛛算法的无人机航迹规划1.群居蜘蛛搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用群居蜘蛛算法来优化无人机航迹规划。 …

【数据结构初阶】顺序表和链表(1)

顺序表和链表&#xff08;1&#xff09; 1.线性表2.顺序表2.1概念以及结构2.1.1静态顺序表2.1.2动态顺序表3.顺序表的实现3.1初始化内容3.2初始化函数3.3销毁函数3.4打印函数3.5扩容函数3.6尾插3.6尾删函数3.7头插函数3.8头删函数3.9查找函数3.10插入函数3.11删除函数3.12修改函…

拿到 phpMyAdmin 如何获取权限

文章目录 拿到 phpMyAdmin 如何获取权限1. outfile 写一句话木马2. general_log_file 写一句话木马 拿到 phpMyAdmin 如何获取权限 1. outfile 写一句话木马 尝试使用SQL注入写文件的方式&#xff0c;执行 outfile 语句写入一句话木马。 select "<?php eval($_REQU…

【软件安装】Windows系统中使用miniserve搭建一个文件服务器

这篇文章&#xff0c;主要介绍如何在Windows系统中使用miniserve搭建一个文件服务器。 目录 一、搭建文件服务器 1.1、下载miniserve 1.2、启动miniserve服务 1.3、指定根目录 1.4、开启访问日志 1.5、指定启动端口 1.6、设置用户认证 1.7、设置界面主题 &#xff08;…
最新文章