一、串口发送数据
1)大概了解
c
RX:接收
TX:发送
连接时需要交叉连接,RX连接对方的TX、TX连接对方的RX
任意的串口都至少需要连接三个引脚:RX、TX、GND
STM32F103C8上有3个串口:USART1、2、3
USART1-TX:PA9
USART1-RX:PA10
TX:复用推挽输出
RX:浮空输入
使用到了复用功能,需要开启复用时钟(AFIO)
2)代码与分析
usart.c
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)
c
当为RESET时表示发送缓冲区不为空,程序会一直停留在这个循环中,
直到数据已经从发送全部发送出去了,USART_FLAG_TXE会被硬件置位1循环结束,下一操作
可以理解为传送带上快递的运输,直到快递全部运输完成,传送带为空
串口引脚的初始化,一般使用推挽输出
波特率、数据位、奇偶校验位、停止位、模式化选择、硬件流控的初始化
USART_Cmd:对前面配置好的串口激活,使能串口1
c
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
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)数据手册
c
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);
c
把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