1.sys文件介绍
2.delay文件介绍
探索者开发板1主要是不使用OS的函数
3.SysTick工作原理
HCLK是AHB高速时钟总线,给VAL传值,VAL不断自减1,到零时,LOAD把自己的值重载在VAL上,开始下一次循环
4.SysTick寄存器
SysTick 控制及状态寄存器 (CTRL)
位段 | 名称 | 类型 | 复位值 | 描述 |
---|---|---|---|---|
16 | COUNTFLAG | R | 0 | 上次读取本寄存器时,systick已数到0,则该值为1;读取该位后,自动清零 |
2 | CLKSORCE | R/W | 0 | 取0时,8分频 取1时,1分频 |
1 | TICKINT | R/W | 0 | 1=sysTick倒数到0时,产生中断 0=sysTick倒数到0时,无动作 |
0 | ENABLE | R/W | 0 | sysTick定时器的开关位(使能位) |
SysTick 重装载数值寄存器 (LOAD)
位段 | 名称 | 类型 | 复位值 | 描述 |
23:0(总共24位) | RELOAD | R/W | 0 | 当倒数至零时,讲被重装再的值 |
SysTick 当前数值寄存器 (VAL)
位段 | 名称 | 类型 | 复位值 | 描述 |
23:0(总共24位) | CURRENT | R/W | 0 | 读取时返回当前倒计数的值,写入则清零,同时还会清除在SysTick控制及状态寄存器中的COUNTFLAG标志 |
5.delay延迟函数
delay_init() 函数
void delay_init(uint16_t sysclk) //探索者版本,频率位168MHZ
{
SysTick->CTRL = 0;
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); //分频为1
g_fac_us = sysclk; //1微秒数168次
}
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(unt16_t nms)
{
unit32_t repeat = nms / 1000; /*这里1000,是考虑到
*可能有超频应用,比如168MHZ,delay_us最大
*只能延时1048576us
*/
uint32_t remain = nms % 1000;
while(repeat)
{
delay_us(1000*1000); //利用delay_us实现1000ms延时
repeat--;
}
if(remain)
{
delay_us(remain * 1000);
}
}
6.usart文件夹介绍
printf的使用
格式一:
printf("字符串\r\n");
格式二:
printf("输出控制符", 输出参数);
格式三:
printf("输出控制符", 输出参数1, 输出参数2);
例子
//格式一
printf("\\\r\n"); // \是转义字符,可以把\后的第一个字符按本来样子发出
//输出\
//格式二
uint32_t temp=10;
printf("%d\r\n", temp); // %d是输出控制符, temp是输出参数
//输出10
//格式三
uint32_t temp=10;
printf("%d %d\r\n", temp1, temp2);
//输出10 10
7.半主机模式
半主机模式定义:通过仿真器实现开发板在电脑上的输入输出,也就是程序运行结果显示在编译程序的主机上
要避免半主机模式有微库法和代码法
部分开发板不支持printf输出,所以还要重定义也是用微库法或代码法
微库法:
代码法:
在项目文件中添加一个文件usart文件,代码如下
/* 加入以下代码, 支持printf函数, 而不需要选择use MicroLIB */
#if 1
#if (__ARMCC_VERSION >= 6010050) /* 使用AC6编译器时 */
__asm(".global __use_no_semihosting\n\t"); /* 声明不使用半主机模式 */
__asm(".global __ARM_use_no_argv \n\t"); /* AC6下需要声明main函数为无参数格式,否则部分例程可能出现半主机模式 */
#else
/* 使用AC5编译器时, 要在这里定义__FILE 和 不使用半主机模式 */
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
#endif
/* 不使用半主机模式,至少需要重定义_ttywrch\_sys_exit\_sys_command_string函数,以同时兼容AC6和AC5模式 */
int _ttywrch(int ch)
{
ch = ch;
return ch;
}
/* 定义_sys_exit()以避免使用半主机模式 */
void _sys_exit(int x)
{
x = x;
}
char *_sys_command_string(char *cmd, int len)
{
return NULL;
}
/* FILE 在 stdio.h里面定义. */
FILE __stdout;
/* 重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{
while ((USART1->SR & 0X40) == 0); /* 等待上一个字符发送完成 */
USART1->DR = (uint8_t)ch; /* 将要发送的字符 ch 写入到DR寄存器 */
return ch;
}
#endif