上一篇:STM32-(15):如何用ID号保护自己的劳动成果 | 下一篇:STM32-(17):SPI与数码管(数码管) |
---|
Systick的两大作用:
1、可以产生精确延时(原先的Delay只是盲等)
2、可以提供给操作系统一个单独的心跳(时钟)节拍
通常实现Delay(N)函数的方法为:
for(i = 0; i <= x; i ++);
x…对应于对应于N毫秒的循环值
对于STM32系列微处理器来说,执行一条指令只有几十个 ns,进行for循环时,要实现N毫秒的x值非常大,而且由于系 统频率的宽广,很难计算出延时N毫秒的精确值。针对STM32 微处理器,需要重新设计一个新的方法去实现该功能,以实现在 程序中使用Delay(N)。
Cortex-M3的内核中包含一个SysTick时钟。SysTick为一个24 位递减计数器,SysTick设定初值并使能后,每经过1个系统时钟周期,计数值就减1。计数到0时,SysTick计数器自动重装初值并继续计数,同时内部的COUNTFLAG标志会置位,触发中断(如果中断使能)。
外部晶振为8MHz,9倍频,系统时钟为72MHz,SysTick的最高频率为9MHz (最大为HCLK/8),在这个条件下,把SysTick效验值设置成9000,将SysTick时钟设置为9MHz,就能够产生1ms的时间基值,即SysTick产生1ms的中断。
SysTick->CALIB 不常用,在这里我们也用不到,故不介绍了。
使用ST的函数库使用systick的方法:
1、 调用 SysTick_CounterCmd()失能 SysTick 计数器
2、 调用 SysTick_ITConfig()失能 SysTick 中断
3、 调用 SysTick_CLKSouceConfig()设置 SysTick 时钟源。
4、 调用 SysTick_SetReload()设置 SysTick 重装载值。
5、 调用 SysTickJTConfig ( ) 使 能 SysTick 中断
6、 调用 SysTick_CounterCmd()开启 SysTick 计数器
//示例
void SysTick_Config(void)
{
/* Disable SysTick Counter */
SysTick_CounterCmd(SysTick_Counter_Disable);
/* Disable the SysTick Interrupt */
SysTick_ITConfig(DISABLE);
/* Configure HCLK clock as SysTick clock source */
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //72MHz/8 = 9MHz
/* SysTick interrupt each 1000 Hz with HCLK equal to 72MHz */
SysTick_SetReload (9000);
/* Enable the SysTick Interrupt */
SysTick_ITConfig(ENABLE);
/* Enable SysTick Counter */
SysTick_CounterCmd(SysTick_Counter_Enable);
}
void Delay_MS(u16dly)
{
Delay = dly;
while( Delay);//这里的Delay的值受下方函数Delay值的影响
}
extern vu16 Delay;
void SysTickHandler(void) //中断服务程序
{
Delay--; //每次COUNTFLAG标志置位,都会触发中断
}
以上例子的特点:①精准;②仍然是忙等(while)
那如何既精准又能去忙别的呢?
/*Include---------------------------*/
#include"stm32f10x_lib.h" //包含所有的头文件
#include
//----------------函数声明--------------------
void Delay_MS(u16 dly);
void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART3_Configuration(void);
u8 tab[]="\nHello! everyone,welcome to class!";
void SYSTICK_Configuration(void)
{
SysTick_CounterCmd(SysTick_Counter_Disable); //失能 SysTick 计数器
SysTick_ITConfig(DISABLE); //失能 SysTick 中断
//设置 SysTick 时钟源
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //9Mhz 系统时钟除以8
//设置 SysTick 重装载值
SysTick_SetReload(9000*1000); //9000/9Mhz 再另外乘以1000,得到的单位时间为1s
//SysTick_ITConfig(ENABLE); //这里不使用
SysTick_CounterCmd(SysTick_Counter_Enable); //开启 SysTick 计数器
}
/*******************************************************************************
* Function Name : main
* Description : Main program.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
int main(void)
{
#ifdef DEBUG
debug();
#endif
u8 sec,min;
//u16 data;
//------------初始化------------
RCC_Configuration();
GPIO_Configuration();
USART3_Configuration();
SYSTICK_Configuration();
printf("\n The Time is: ");
sec = 30;
min = 1; //从一分三十秒开始计数,实现当秒数大于60,分数进位
//------------将秒和分的数据上传到上位机------------
while(1)
{
FlagStatus Status;
Status = SysTick_GetFlagStatus(SysTick_FLAG_COUNT);
if(Status == RESET) //标志位清零不做操作
{
}
else //标志位置1,秒数增加
{
sec++;
if(sec == 60)
{
sec = 0;
min++;
}
printf("%d:%d\t",min,sec);
}
}
}
/*******************************************************************************
* Function Name : Delay_Ms
* Description : delay 1 ms.
* Input : dly (ms)
* Output : None
* Return : None
*******************************************************************************/
void Delay_MS(u16 dly)
{
u16 i,j;
for(i=0;i0;j--);
}
/*******************************************************************************
* Function Name : RCC_Configuration
* Description : Configures the different system clocks.
* Input : None
* Output : None
* Return : None
************************************************************ *******************/
void RCC_Configuration(void)
{
//----------使用外部RC晶振-----------
RCC_DeInit(); //初始化为缺省值
RCC_HSEConfig(RCC_HSE_ON); //使能外部的高速时钟
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); //等待外部高速时钟使能就绪
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Enable Prefetch Buffer
FLASH_SetLatency(FLASH_Latency_2); //Flash 2 wait state
RCC_HCLKConfig(RCC_SYSCLK_Div1); //HCLK = SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1); //PCLK2 = HCLK
RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1 = HCLK/2
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //PLLCLK 8MHZ * 9 =72MHZ(SYSCLK)
RCC_PLLCmd(ENABLE); //Enable PLLCLK
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait till PLLCLK is ready
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //Select PLL as system clock
while(RCC_GetSYSCLKSource()!=0x08); //Wait till PLL is used as system clock source
//---------打开相应外设时钟--------------------(在这里,需要打开的都是外设时钟,而Systick属于内核,会自动开启)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO,ENABLE); //使能APB2外设的GPIOA的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
}
/*******************************************************************************
* Function Name : GPIO_Configuration
* Description : 初始化GPIO外设
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //选择PC.10(TXD) 和 PC.11
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //输出模式为复用推挽输出
GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOC寄存器
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //选择PC.10(TXD) 和 PC.11(RXD)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //输出模式为浮空输入
GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOA寄存器
//将USART3的TXD和RXD重映射到PC10和pc11
GPIO_PinRemapConfig(GPIO_PartialRemap_USART3,ENABLE);
}
void USART3_Configuration(void)
{
USART_InitTypeDef U3;
U3.USART_BaudRate =9600;
U3.USART_WordLength = USART_WordLength_8b;
U3.USART_StopBits = USART_StopBits_1;
U3.USART_Parity = USART_Parity_No;
U3.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
U3.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART3, &U3);
USART_Cmd(USART3,ENABLE);
}
/*******************************************************************************
* Function Name : fputc
* Description : 重定向这个C库(stdio)printf函数 文件流——》串口USART1
* Input : ch,*f
* Output : None
* Return : None
*******************************************************************************/
int fputc(int ch,FILE *f)
{
//ch送给USART1
USART_SendData(USART3, ch);
//等待发送完毕
while(USART_GetFlagStatus(USART3, USART_FLAG_TC)==RESET) ;
//返回ch
return(ch);
}
注:下位机(ARM的Coretex芯片)发送到上位机的显示窗口(PC机串口),这个串口工具的输入窗口可以发送数据(图中内容为“源享科技”的地方),就是从上位机发送到下位机。
上一篇:STM32-(15):如何用ID号保护自己的劳动成果 | 下一篇:STM32-(17):SPI与数码管(数码管) |
---|