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

1.deley文件夹介绍

1.1.delay文件夹介绍

函数名函数功能OS
delay_osschedlockus级延时时,关闭任务调度(防止打断us级延迟)OS
delay_osschedunlockus级延时时,恢复任务调度OS
delay_ostimedlyus级延时时,恢复任务调度OS
SysTick_Handlersystick中断服务函数OS
delay_init初始化延迟函数OS/no OS
delay_us延时nusOS/no OS
delay_ms延时musOS/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的使用

  1. printf(“字符串\r\n”)
printf("Hello World!\r\n");
  1. printf(“输出控制符”,输出参数)
uint32_t  temp = 10;
printf("%d\r\n", temp);          /* %d是输出控制符,temp是输出参数 */
  1. printf(“输出控制符1输出控制符2…”,输出参数1,输出参数2,…)
uint32_t  temp1 = 5;   
uint32_t  temp2 = 10;
printf("%d%x \r \n", temp1,temp2); 
  1. printf(“非输出控制符 输出控制符 非输出控制符”,输出参数);
uint32_t  temp = 10;   
printf("temp=  %d  收到over\r\n", temp);  
  1. 如何输出%、\和双引号
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语句不可以屏蔽,否则会出现乱码的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值