STM32F407VET6 学习笔记2:定时器、串口、自定义串口打印函数

今日继续学习使用嘉立创购买的 立创梁山派天空星,芯片是 STM32F407VET6

因为已经有学习基础了,所以学习进度十分快,这次也是直接一块学习配置定时器与串口了,文章也愈来愈对基础的解释越来越少了......

文章提供测试代码讲解、完整工程下载、测试效果图

 

本文学习目标:

配置串口发送功能,自定义串口print函数、定时器计数计时中断功能,定时器每隔1000ms使用串口发送一次数据

目录

串口通信的配置:

串口初始化:

串口中断服务函数:

自定义串口打印函数:

开发板硬件连接:

测试代码结果:

定时器的计时功能配置:

定时器初始化:

定时器时钟来源:

定时中断频率计算:

定时中断服务函数:

测试效果图:

测试工程下载:


串口通信的配置:

我个人认为,基础的串口通信主要有以下几方面重要:

1、串口的初始化:打开外设总线、引脚配置、波特率配置、中断优先级配置

2、串口中断服务函数的编写

3、串口发送简单,但接收逻辑要写清除比较难

(通常定义结构体、状态机思维接收、处理错误数据丢包等......)

但今日主要还是只关注  配置使用串口的发送功能 即可......

 

串口初始化:

整个函数基本步骤简单来讲就是:

开总线、配引脚、设串口参数、开接收中断、配中断优先级......

下面是初始化串口1   PA9 (TX) 、PA10 (RX)的例程代码:

void uart1_init(uint32_t __Baud)
{GPIO_InitTypeDef GPIO_InitStructure;	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);//IO口用作串口引脚要配置复用模式GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);GPIO_StructInit(&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin           = GPIO_Pin_9;//TX引脚GPIO_InitStructure.GPIO_Mode          = GPIO_Mode_AF;//IO口用作串口引脚要配置复用模式GPIO_InitStructure.GPIO_Speed         = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_OType         = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd          = GPIO_PuPd_UP;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_StructInit(&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin           = GPIO_Pin_10;//RX引脚GPIO_InitStructure.GPIO_Mode          = GPIO_Mode_AF;GPIO_InitStructure.GPIO_Speed         = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_OType         = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd          = GPIO_PuPd_UP;GPIO_Init(GPIOA,&GPIO_InitStructure);USART_InitTypeDef USART_InitStructure;//定义配置串口的结构体变量RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//开启串口1的时钟USART_DeInit(USART1);//大概意思是解除此串口的其他配置USART_StructInit(&USART_InitStructure);USART_InitStructure.USART_BaudRate              = __Baud;//设置波特率USART_InitStructure.USART_WordLength            = USART_WordLength_8b;//字节长度为8bitUSART_InitStructure.USART_StopBits              = USART_StopBits_1;//1个停止位USART_InitStructure.USART_Parity                = USART_Parity_No ;//没有校验位USART_InitStructure.USART_Mode                  = USART_Mode_Rx | USART_Mode_Tx;//将串口配置为收发模式USART_InitStructure.USART_HardwareFlowControl   = USART_HardwareFlowControl_None; //不提供流控 USART_Init(USART1,&USART_InitStructure);//将相关参数初始化给串口1USART_ClearFlag(USART1,USART_FLAG_RXNE);//初始配置时清除接受置位USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//初始配置接受中断USART_Cmd(USART1,ENABLE);//开启串口1NVIC_InitTypeDef NVIC_InitStructure;//中断控制结构体变量定义NVIC_InitStructure.NVIC_IRQChannel                    = USART1_IRQn;//中断通道指定为USART1NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority  = 0;//主优先级为0NVIC_InitStructure.NVIC_IRQChannelSubPriority         = 1;//次优先级为1NVIC_InitStructure.NVIC_IRQChannelCmd                 = ENABLE;//确定使能NVIC_Init(&NVIC_InitStructure);//初始化配置此中断通道}

 

串口中断服务函数:

/******** 串口1 中断服务函数 ***********/
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)//判断是不是真的有中断发生{//USART_SendData(USART1,USART_ReceiveData(USART1));//又将数据发回去(用于验证)USART_ClearITPendingBit(USART1, USART_IT_RXNE); //已经处理就清楚标志位 }  
}

 

自定义串口打印函数:

这是个很有意思的自定义打印函数,可以让你的任意串口打印都能像用printf函数一样方便:

注意需要添加以下头文件:

#include "stdarg.h"      //自定义printf需要使用
#include "stdio.h"       //1.61328125kb

//选择串口发送数据--自定义Printf
void UsartPrintf (USART_TypeDef *USARTx, char *fmt,...)
{unsigned char UsartPrintfBuf[296];                                  //最大长度296va_list ap;unsigned char *pStr = UsartPrintfBuf;va_start(ap, fmt);vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);	//格式化va_end(ap);while(*pStr != 0){USART_SendData(USARTx, *pStr++);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);}
}

 

开发板硬件连接:

这里需要注意UART1的TX与RX引脚就在背面:不用处心积虑寻找PA9与PA10了哈:

注意与usb转串口模块连接时tx接rx,rx接tx就行了:

测试代码结果:

 这里也是使用自己写的不靠谱串口助手上位机软件测试代码接收成功了:

 

 

定时器的计时功能配置:

个人总结定时器无非几个重要功能:计数计时、输出PWM、捕获脉冲计数

配置计时器的时候需要注意以下几点:

定时器接的时钟频率、定时器分频、最大重载值、计数模式、中断优先级

GD32F407VET6一共有14个定时器,可以分为五种类型,高级定时器0/7、通用定时器(L0)1-4、通用定时器(L1)8/11、通用定时器(L2)9/10/12/13和基本定时器5/6。不同类型的定时器所拥有的功能数量不同,一般高级定时器的功能最多,通用定时器次之,基本定时器功能最少。具体功能对照可以查看用户手册的第349页。 

 

定时器初始化:

//接受两个整数参数:Period和Prescaler。Period是定时器的周期值,而Prescaler是预分频值。
void Timer_init(int Period,int Prescaler)
{//定义了两个结构体变量,用于配置定时器和NVIC(嵌套向量中断控制器)TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;NVIC_InitTypeDef NVIC_InitStructure;//启用TIM3的时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频设置为1(即不分频)TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//计数器模式设置为向上计数TIM_TimeBaseStructure.TIM_Period = Period;//周期和预分频值分别设置为函数的参数值。TIM_TimeBaseStructure.TIM_Prescaler = Prescaler;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);//使用TIM_TimeBaseInit函数将这些配置应用到TIM3上。//启用了TIM3的更新中断。当定时器的计数值达到周期值时,会产生一个更新中断。TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);//配置了NVIC以处理TIM3的中断。设置了中断通道为TIM3_IRQn,启用了该中断,并设置了抢占优先级和子优先级。NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;NVIC_Init(&NVIC_InitStructure);//启动了TIM3定时器TIM_Cmd(TIM3,ENABLE);
}	

 

定时器时钟来源:

这在数据手册18页:

可以看到14个定时器的时钟来源主要分为两部分,第一部分来源于CK_APB1,第二部分来源于CK_APB2。然后经过时钟配置寄存器(RCU_CFG1)决定是APB频率的2倍还是4倍,但这个频率不能超过AHB(max = 168MHZ)。

这里使用TIMER3,就要先使能TIMER5的时钟,又因为TIMER3时钟来源于CK_APB1,CK_APB1的时钟在system_stm32f4xx.c中定义

从图可以看到APB1的时钟等于AHB的时钟4分频,

AHB的时钟等于系统时钟SYSCLK 也就是168Mhz

那么APB1的时钟就是168/4=42Mhz

APB1的时钟再经过CK_APB1的2倍频传给定时器,即84Mhz

定时中断频率计算:

预分频器可以将定时器的时钟(TIMER_CK)频率按1到65536之间的任意值分频,分频后的时钟PSC_CLK驱动计数器计数。分频系数受预分频器TIMERx_PSC控制。这个控制寄存器带有缓冲器,它能够在运行时被改变。新的预分频器的参数在下一次更新事件到来时被采用。

分频器的分频公式为:PSC_CLK = TIMER_CK/ (TIMERx_PSC +1)

计数器溢出频率:   

CK CNT_OV= CK CNT   /    (ARR+1)

                     =  CK PSC  /    (PSC +1)  /  (ARR +1)          单位:Hz

由上文知CK PSC =  84Mhz

因此,为了达到1000ms溢出的速率,我们可以将period(即ARR)设为10000,将Prescaler(即PSC)设为8400

定时中断服务函数:

 


//定时器TIM3中断服务函数:
void TIM3_IRQHandler(void)
{if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET){ // {}中为中断处理i++;UsartPrintf(USART1," %d seconds past \r\n",i);	//开机打印测试字符串}TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}

测试效果图:

测试工程下载:

https://download.csdn.net/download/qq_64257614/89276407

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【如此简单!数据库入门系列】之思想地图 -- 系列目录

文章目录 1 前言2 基本概念3 基本原理4 数据库历史5 数据模型6 数据库规范化7 数据存储8 总结 1 前言 目录是思想地图,指引我们穿越文字的森林。 为了方便系统性阅读,将【如此简单!数据库入门系列】按照模块划分了目录结构。 2 基本概念 【…

Jetpack Compose(一

Intellij IDEA构建Android开发环境 IntelliJ IDEA 2023.2.1 Android开发变化 IDEA配置使用Gradle 新建Compose工程,取名ComposeStudy 可以看到的是IDEA为项目初始化了部分代码 使用Compose开发不再需要使用xml文件来设计布局了 Compose中的Text也不同于Android V…

ogv转mp4怎么转?只需3个步骤~

OGV(Ogg Video)是一种开源的视频文件格式,起源于对数字媒体领域的开放标准的需求。作为Ogg多媒体容器的一部分,OGV的设计初衷是提供一种自由、高质量的视频编码方案,以满足多样化的应用需求。 支持打开MP4文件格式的软…

119. 再谈接口幂等性

文章目录 0. 前言1. insert前先select2. 加悲观锁3. 加乐观锁5. 加唯一索引【配合 (1. insert前先select )最常用 】6. 建防重表6. 根据状态机7. 加分布式锁8. 获取token 0. 前言 在 93. 通用防重幂等设计 一文中,已经介绍过幂等的使用。该文…

【一看就懂】UART、IIC、SPI、CAN四种通讯协议对比介绍

UART、IIC、SPI、CAN四种通信协议对比 通信方式传输线通讯方式标准传输速度使用场景UARTTX(发送数据线)、RX(接收数据线)串行、异步、全双工115.2 kbit/s(常用)计算机和外部设备通信(打印机)IICSCL(时钟线)、SDA(数据线)串行、同步、半双工100 kbit/s(标…

一种由RSOA和PIC集成的宽可调激光器

----翻译自Nouman Zia, Samu-Pekka Ojanen, Jukka Viheriala, Eero Koivusalo, Joonas Hilska, Heidi Tuorila, and Mircea Guina在optics letter上发的文章vol.48, Issue 5, pp. 1319-1322(2023) 摘要:通过光子集成方式实现的2-3μm波长的可调激光器,在…

Adobe Acrobat Pro DC 2022一款高效强大的PDF阅读编辑专业软件(240506)

01 软件介绍 Adobe Acrobat Pro DC 2022,作为一款专业的PDF处理工具,它集成了强大的制作功能,能够与Adobe Photoshop的高级图像编辑能力无缝衔接,进而将各类纸质文档高效转换成可编辑的电子格式,以便于文件的传输和签…

跨越语言界限,多语言盲盒小程序带你领略全球风情

在全球化的今天,我们生活在一个多元文化的世界中,不同的语言、风俗、习惯共同构成了这个五彩斑斓的地球村。为了让每个人都能轻松体验到世界各地的独特风情,一款创新的多语言盲盒小程序应运而生,它跨越了语言的界限,让…

老阳分享:跨境选品师普通人做能否借此赚钱?

在跨境电商日益繁荣的今天,选品师这一职业逐渐进入大众视野。老阳,作为业内知名的跨境选品师,经常分享他的选品经验和心得。那么,对于普通人来说,成为跨境选品师是否真的能赚钱呢? 首先,我们需要明确什么是…

mySQL (基础面试)实物四属性 ACID属性,以及开启事务

mySQL具备四个基本属性 原子性atomicity 事务是一个完整的操作,事务的各个步骤是不可分的(原子的),要么执行要么不执行 一致性consistency 当事务完成时,数据处于一致状态 隔离性isolation 并发事物之间彼此隔离…

基于springboot+vue+Mysql的租房网站

开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…

springboot3项目练习详细步骤(第二部分:文章分类模块)

新增文章分类 接口文档 业务实现 参数校验 文章分类列表 接口文档 业务实现 获取文章分类详情 接口文档 业务实现 更新文章分类 接口文档 业务实现 分组校验 问题 概念 实现步骤 总结 删除文章分类 接口文档 业务实现 该模块大部分请求的路径相同&…

2024最新行业领域名词解释大全

2024最新行业领域名词解释大全 🚀 大家好!我是你们的老朋友猫头虎🐯。今天要为大家带来2024年最新的行业领域名词解释大全!在这个信息爆炸的时代,准确了解不同领域的行业动态、工作机会和职业前景至关重要。下面我会分…

阿里巴巴中国站关键字搜索API返回值全攻略:精准定位所需商品

当使用阿里巴巴中国站的关键字搜索API时,理解其返回值的结构和内容对于精准定位所需商品至关重要。以下是一份全面的攻略,帮助你更好地利用这个API: 在商品列表中,每个商品对象都包含丰富的信息,以帮助你精准定位所需商…

伙伴匹配(后端)-- 前后端日期格式化

后端时间格式化 后端时间格式化 在expireTime属性加上一个格式化注解,并给定格式 前端过期时间格式化 下载一个moment格式化工具(我安装失败了日期格式化也成功了) npm install moment这一页和添加队伍新增这一行(还要导入mom…

Python数据爬取超简单入门

## 什么是网络爬虫? 网络爬虫是一种自动浏览器程序,能够自动地从互联网获取数据。爬虫的主要任务是访问网页,分析网页内容,然后提取所需的信息。爬虫广泛应用于数据收集、数据分析、网页内容监控等领域。 ## 爬虫的基本步骤 1.…

2025第23届太原煤炭(能源)工业技术与装备展览会

第二十三届太原煤炭(能源)工业技术与装备展览会 邀 请 函 指导单位: 中国煤炭工业协会 主办单位:山西省煤炭工业协会 承办单位:太原奇新展览有限公司 展览时间:2025年4月22-24日 展览地点&#xff1a…

Obsidian dataview 使用入门

Dataview有四种展示格式:list、table、task、calendar。 本文只介绍前面两种。 语法总结 通过#标签 dataview LIST FROM #标签 通过"文件夹" dataview LIST FROM "文件夹名" 通过[ [ 文件链接 ] ] 选择链接到一个文件,或者…

深入了解C/C++的内存区域划分

🔥个人主页:北辰水墨 🔥专栏:C学习仓 本节我们来讲解C/C的内存区域划分,文末会附加一道题目来检验成果(有参考答案) 一、大体有哪些区域?分别存放什么变量开辟的空间? …

探索AI编程新纪元:从零开始的智能编程之旅

提示:Baidu Comate 智能编码助手是基于文心大模型,打造的新一代编码辅助工具 文章目录 前言AI编程概述:未来已来场景需求:从简单到复杂,无所不包体验步骤:我的AI编程初探试用感受:双刃剑下的深思…