1.deley文件夹介绍
1.1.delay文件夹介绍
函数名 | 函数功能 | OS |
---|---|---|
delay_osschedlock | us级延时时,关闭任务调度(防止打断us级延迟) | OS |
delay_osschedunlock | us级延时时,恢复任务调度 | OS |
delay_ostimedly | us级延时时,恢复任务调度 | OS |
SysTick_Handler | systick中断服务函数 | OS |
delay_init | 初始化延迟函数 | OS/no OS |
delay_us | 延时nus | OS/no OS |
delay_ms | 延时mus | OS/no OS |
1.2.SysTick工作原理
SysTick,即系统滴答定时器,包含在M3/4/7内核里面,核心是一个24位的递减计数器
每次VAL到0时,VAL自动从LOAD重载!开始新一轮递减计数。
1.3.SysTick寄存器介绍
-
SysTick控制及状态寄存器(CTRL)
-
SysTick重装载数值寄存器(LOAD)
-
SysTick当前数值寄存器(VAL)
1.4.关键程序
SysTick的时钟源自HCLK,假设配置系统时钟为72MHZ,经过分频器8分频后,那么SysTick 的时钟即为9Mhz,也就是SysTick 的计数器VAL每减1,就代表时间过了1/9us 。
此外,HAL库也提供了HAL_Delay()函数,但是误差较大,不建议使用。在HAL_Init()函数虽然做了SysTick的初始化,但是在delay_init()函数中又做了初始化,覆盖了之前的初始化。
- delay_init()函数
void delay_init(uint16_t sysclk)
{
SysTick->CTRL = 0;
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8);
g_fac_us = sysclk / 8;
}
- delay_us()函数
void delay_us(uint32_t nus)
{
uint32_t temp;
SysTick->LOAD = nus * g_fac_us; /* 时间加载 */
SysTick->VAL = 0x00; /* 清空计数器 */
SysTick->CTRL |= 1 << 0 ; /* 开始倒数 */
do
{
temp = SysTick->CTRL;
} while ((temp & 0x01) && !(temp & (1 << 16))); /* CTRL.ENABLE位必须为1, 并等待时间到达 */
SysTick->CTRL &= ~(1 << 0) ; /* 关闭SYSTICK */
SysTick->VAL = 0X00; /* 清空计数器 */
}
- delay_ms()函数
void delay_ms(uint16_t nms)
{
uint32_t repeat = nms / 1000; /* 这里用1000,是考虑到可能有超频应用,
* 比如128Mhz的时候, delay_us最大只能延时1048576us
*/
uint32_t remain = nms % 1000;
while (repeat)
{
delay_us(1000 * 1000); /* 利用delay_us 实现 1000ms 延时 */
repeat--;
}
if (remain)
{
delay_us(remain * 1000); /* 利用delay_us, 把尾数延时(remain ms)给做了 */
}
}
2.sys文件夹介绍
3.usart文件夹介绍
3.1.printf函数输出流程
3.2.printf的使用
- printf(“字符串\r\n”)
printf("Hello World!\r\n");
- printf(“输出控制符”,输出参数)
uint32_t temp = 10;
printf("%d\r\n", temp); /* %d是输出控制符,temp是输出参数 */
- printf(“输出控制符1输出控制符2…”,输出参数1,输出参数2,…)
uint32_t temp1 = 5;
uint32_t temp2 = 10;
printf("%d%x \r \n", temp1,temp2);
- printf(“非输出控制符 输出控制符 非输出控制符”,输出参数);
uint32_t temp = 10;
printf("temp= %d 收到over\r\n", temp);
- 如何输出%、\和双引号
printf("%% \r\n");
printf("\\\r\n");
printf("\"\"\r\n");
3.3.printf函数支持
-
半主机模式:用于 ARM 目标的一种机制,可将来自应用程序代码的输入/输出请求传送至运行调试器的主机,就是通过仿真器实现开发板在电脑上的输入和输出,一般我们不使用半主机模式。
-
避免半主机模式方法1:微库法
在魔术棒->Target选项卡,勾选:Use Micro LIB,即可避免半主机模式。
-
避免半主机模式方法2:代码法(详见usatr.c)
1,#pragma import(__use_no_semihosting),确保不从C库中使用半主机函数
2,定义:__FILE结构体,避免HAL库某些情况下报错
3,定义: FILE __stdout,避免编译报错
4,实现:_ttywrch、_sys_exit和_sys_command_string等三个函数
AC5和AC6不使用半主机模式稍有差异,详见源码。
3.4.实现fputc函数的重定向
代码如下:
#define USART_UX USART1
/* MDK下需要重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{
while ((USART_UX->SR & 0X40) == 0); /* 等待上一个字符发送完成 */
USART_UX->DR = (uint8_t)ch; /* 将要发送的字符 ch 写入到DR寄存器 */
return ch;
}
注意:while语句不可以屏蔽,否则会出现乱码的情况。