当前位置: 首页 > article >正文

串口发送数据,SysTick定时器的实现

一、串口发送数据

1)大概了解

RX:接收
TX:发送
连接时需要交叉连接,RX连接对方的TX、TX连接对方的RX
任意的串口都至少需要连接三个引脚:RX、TX、GND
STM32F103C8上有3个串口:USART1、23
USART1-TX:PA9
USART1-RX:PA10
TX:复用推挽输出
RX:浮空输入
使用到了复用功能,需要开启复用时钟(AFIO)

2)代码与分析

usart.c

int fputc(int ch,FILE *file)
{
    USART_SendData(USART1,ch);
    //等待发送完成
    while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
    
    return ch;
}

输出重定向:即能够在串口上显示,若没有这个函数串口不会显示任何数据(将原本输出到标准设备的内容发送到串口)
USART_SendData(USART1,ch):将字符ch发送到 USART1串口的数据寄存器中启动发送流程。
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET)

当为RESET时表示发送缓冲区不为空,程序会一直停留在这个循环中,
直到数据已经从发送全部发送出去了,USART_FLAG_TXE会被硬件置位1循环结束,下一操作
可以理解为传送带上快递的运输,直到快递全部运输完成,传送带为空

在这里插入图片描述

在这里插入图片描述
串口引脚的初始化,一般使用推挽输出
在这里插入图片描述
波特率、数据位、奇偶校验位、停止位、模式化选择、硬件流控的初始化
USART_Cmd:对前面配置好的串口激活,使能串口1

void send_char(char ch)
{
    USART_SendData(USART1,ch);
    //等待发送完成
    while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);//表示标志位未被置位,即发送缓冲区不为空,程序会一直停留在这个循环中
                                                             //只有当发送缓冲区为空(即数据已经从发送缓冲区发送出去了)
                                                             //USART_FLAG_TXE标志被置位,此时USART_GetFlagStatus函数返回非RESET值,循环结束
                                                             //USART_FLAG_TXE(发送数据寄存器为空标志)是由硬件自动置位的
}

在这里插入图片描述
跟上诉原理一致,循环遍历每一个字符
.h
在这里插入图片描述
main.c

#include "stm32f10x.h"                  // Device header
#include "printf.h"
#include "stdio.h"

void delay_ms(int x)
{
    int i=0;
    while(x--)
        for(i=0;i<8050;i++);
}

int main()
{
    int i=0;
    printf_init(9600);
    while(1)
    {
        //Send_Char('A');
		//delay_ms(10);
        printf("i=%d\r\n",i++);
        delay_ms(10);
        printf("hello world\n");
        delay_ms(10);
    }
}

二、SysTick

1)数据手册

在这里插入图片描述

COUNTFLAG:计数标志位
如果计时器自上次读取以来计数为0,则返回1

CLKSOURCE:时钟源设置,AHB默认72MHz
0:AHB/8
1:AHB

TICKINT:中断使能位
0:倒计时到0不产生中断
1:倒计时到0产生中断

ENABLE:SysTick使能位
0:关闭定时器
1:开启定时器

在这里插入图片描述
在这里插入图片描述

2)代码与分析

在这里插入图片描述
将时钟进行8分频,得到AHB/8=9MHz
在这里插入图片描述
SysTick->LOAD:重装载值设置为8999999(定时器在启动时会将这个值加载到内部的计数逻辑中),直到减位0时进行了9000000次
SysTick->VAL:让定时器从一个确定的初始状态开始计数。这里的初始状态是指定时器内部的计数逻辑部分,确保它在开始计数时没有受到之前可能遗留的计数值的干扰。
SysTick->CTRL &= ~(1<<1):倒计时到0时不产生中断
SysTick->CTRL |=1:使能ENABLE,打开定时器。
一旦定时器启动,定时器的计数逻辑会从SysTick->LOAD寄存器获取初始值,也就是9000000 - 1
这个值会被加载到用于实际计数的内部寄存器(这个内部寄存器和SysTick->VAL有联系,但在启动时是从SysTick->LOAD加载初始值),也就是VAL从初始值处开始递减
while(SysTick->CTRL & (1<<16)==0);

把SysTick->CTRL寄存器想象成一个 32 个小格子(位)组成的盒子,每个小格子可以放 0 或者 1(1 << 16)这个操作,就像是在一个新的 32 个小格子组成的盒子里,把一个 “1” 从最右边(第 0 位)开始,
向左移动 16 个小格子,这样就得到了一个只有第 16 个小格子是 “1”,其他小格子都是 “0” 的盒子。

一开始,SysTick->CTRL这个盒子的第 16 个小格子(代表计数到 0 的信号)是 “0”
,当我们进行SysTick->CTRL & (1 << 16)操作时,得到的结果也是 “0”
就像小机器人还没收到信号,所以它会一直等在while循环里

随着 SysTick 定时器在后台默默地计数,就好像有一个隐藏的倒计时在进行。
当这个倒计时结束,也就是定时器计数到 0 的时候,硬件会把SysTick->CTRL盒子的第 16 个小格子变成 “1”
时再进行SysTick->CTRL & (1 << 16)操作,得到的结果就不是 “0” 了
程序就知道定时器已经计数到 0 了,延时完成,于是它就跳出while循环,继续后面的工作

最后再关闭定时器,形成闭环也就是1s


http://www.kler.cn/a/468112.html

相关文章:

  • 《Vue3实战教程》19:Vue3组件 v-model
  • 【开源工业视觉库】启航规划
  • Uniapp Android 本地离线打包(详细流程)
  • k620老显卡,装cuda.等。
  • 对一个双向链表,从尾部遍历找到第一个值为x的点,将node p插入这个点之前,如果找不到,则插在末尾。使用C语言实现
  • 计算机网络练习题
  • BUUCTF sqli-labs 1
  • 不只是mini-react第一节:实现最简单mini-react
  • C#—SynchronizationContext类详解 (同步上下文)
  • hashMap追问
  • Python 中利用装饰器实现多线程函数调用示例
  • 利用Deeplearning4j进行 图像识别
  • Quartus与Synopsys联合调试
  • Golang中的通道和缓冲区
  • 计算机网络相关术语
  • 2025加密风云:行业变革与未来趋势全景透视
  • 2025/1/4期末复习 密码学 按老师指点大纲复习
  • 【51项目】51单片机自制小霸王游戏机
  • 【SpringBoot3】Spring Boot 3.0 集成 Mybatis Plus
  • 医学图像分析工具02:3D Slicer || 医学影像可视化与分析工具 支持第三方插件
  • AI辅助的运维流程自动化:实现智能化管理的新篇章
  • connect to host github.com port 22: Connection timed out 的解决方法
  • R语言的数据结构
  • 城市供水管网多普勒超声波流量计,保障供水安全
  • 【游戏设计原理】46 - 魔杖
  • 一种新的混合大模型架构:TITAN