【嵌入式学习笔记】嵌入式基础11——STM32常用轮子(SYSTEM)

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()函数
cpp 复制代码
void delay_init(uint16_t sysclk) 
{ 
	SysTick->CTRL = 0; 
	HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8); 
	g_fac_us = sysclk / 8; 
}
  • delay_us()函数
cpp 复制代码
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()函数
cpp 复制代码
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的使用

  1. printf("字符串\r\n")
cpp 复制代码
printf("Hello World!\r\n");
  1. printf("输出控制符",输出参数)
cpp 复制代码
uint32_t  temp = 10;
printf("%d\r\n", temp);          /* %d是输出控制符,temp是输出参数 */
  1. printf("输出控制符1输出控制符2...",输出参数1,输出参数2,...)
cpp 复制代码
uint32_t  temp1 = 5;   
uint32_t  temp2 = 10;
printf("%d%x \r \n", temp1,temp2); 
  1. printf("非输出控制符 输出控制符 非输出控制符",输出参数);
cpp 复制代码
uint32_t  temp = 10;   
printf("temp=  %d  收到over\r\n", temp);  
  1. 如何输出%、\和双引号
cpp 复制代码
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函数的重定向

代码如下:

cpp 复制代码
#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语句不可以屏蔽,否则会出现乱码的情况。

相关推荐
Jackilina_Stone8 分钟前
【HUAWEI】HCIP-AI-MindSpore Developer V1.0 | 第一章 神经网络基础(4 生成对抗网络 ) | 学习笔记
人工智能·笔记·神经网络·生成对抗网络·华为·hcip
Jackilina_Stone12 分钟前
【HUAWEI】HCIP-AI-MindSpore Developer V1.0 | 第一章 神经网络基础( 3 循环神经网络 ) | 学习笔记
人工智能·笔记·rnn·神经网络·hcip·huawei
长安不及十里33 分钟前
操作日志设计(一) Binlog 方案(Canal+Mq)
分布式·后端·学习·云原生
秦明月1340 分钟前
【原创学习笔记】实际调试遇到的问题01
笔记·学习
逝灮1 小时前
【蓝桥杯——物联网设计与开发】Part2:OLED
驱动开发·stm32·单片机·嵌入式硬件·物联网·蓝桥杯·oled
我自飞扬临天下1 小时前
Elasticsearch操作笔记版
java·笔记·elasticsearch
Jackilina_Stone2 小时前
【HUAWEI】HCIP-AI-MindSpore Developer V1.0 | 第一章 神经网络基础( 2 卷积神经网络 ) | 学习笔记
人工智能·笔记·深度学习·神经网络·cnn
加酶洗衣粉2 小时前
PostgreSQL学习笔记(一):PostgreSQL介绍和安装
笔记·学习·postgresql
大佬,救命!!!2 小时前
重新整理机器学习和神经网络框架
人工智能·笔记·深度学习·神经网络·机器学习·类比学习
人工智能技术咨询.2 小时前
工信部电子标准院计算机视觉证书报考指南!
人工智能·深度学习·学习·计算机视觉·语言模型