Systick的两大作用: 1、可以产生精确延时; 2、可以提供给操作系统一个单独的心跳(时钟)节拍; 通常实现Delay(N)函数的方法为: for(i=0;i<x;i++) ; 对于STM32系统微处理器来说,执行一条指令只有几十ns(纳秒),进入for循环,要实现N毫秒的x值非常大;而由于系统频率的宽广,很难计算出延时N毫秒的精确值;针对STM32微处理器,需要重新设计一个新的方法去实现该功能,以实现在程序中使用Delay(N); cortex的内核中包含一个SysTick时钟,SysTick为一个24位递减计数器;SysTick设定初值并使能后,每经过1个系统时钟周期,计数值就减1;计数到0,SysTick计数器自动装载初值并继续计数,同时内部的COUNTFLAG标志会置位;触发中断(前提是中断使能); 如果外部晶振(即外接的晶振)位8Mhz,经过内部9分频;系统时钟则为72Mhz(cpu的时钟);SysTick的最高频率为9Mhz(cpu时钟的8分频);在这个条件下;如果设置SysTick值为9000;而SysTick是9Mhz;则能产生1ms的时间基;即SysTick产生1ms的中断;
SysTick相关的寄存器: CTRL: SysTick控制和状态寄存器; LOAD: SysTick重装载值寄存器; VAL: SysTick当前寄存器;(重新写入的时候;会把状态寄存器的FLAG清零) CALIB: SysTick校准值寄存器; SysTick设置步骤:(使用ST的函数库使用Systick的方法) 1、调用SysTick_CounterCmd()失能SysTick计数器; 2、调用SysTick_ITConfig()失能SysTick中断; 3、调用SysTick_CLKSourceConfig()设置SysTick时钟源; 4、调用SysTick_SetReload() 设置SysTick重装载值; 5、调用SysTick_ITConfig() 使能SysTick中断; 6、调用SysTick_CounterCmd() 开启SysTick计数器;
- /*Include---------------------------*/
- #include"stm32f10x_lib.h" //包含所有的头文件
- #include<stdio.h>
- //----------------函数声明--------------------
- void Delay_MS(u16 dly);
- void RCC_Configuration(void);
- void GPIO_Configuration(void);
- void USART3_Configuration(void);
- u8 tab[] = "hello welcome to class !";
- void SYSTICK_Configuration(void)
- {
- SysTick_CounterCmd(SysTick_Counter_Disable);
- SysTick_ITConfig(DISABLE);
- SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
- SysTick_SetReload(9000*1000);
- SysTick_CounterCmd(SysTick_Counter_Enable);
- //*************打开systick时钟,但是由于systick时钟是默认开启的;
-
- }
- /*******************************************************************************
- * Function Name : main
- * Description : Main program.
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
- int main(void)
- {
- u8 min, sec;
- #ifdef DEBUG
- debug();
- #endif
- //------------初始化------------
- RCC_Configuration();
- GPIO_Configuration();
- USART3_Configuration();
- SYSTICK_Configuration();
- // id_num[0] = *((u8*)(0x1FFFF7E9)); //stm32芯片id的放置地址,96位id;12字节
- printf("hello world\n");
- //------------将数据上传给上位机-----------
- min = 1;
- sec = 30;
- while(1)
- {
- FlagStatus Status;
- Status = SysTick_GetFlagStatus(SysTick_FLAG_COUNT);
- if(Status == RESET)
- {
- ;
- }
- else
- {
- sec++;
- if(sec == 60)
- {
- sec=0;
- min++;
- }
- printf("\t\t%d:%d", 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;i<dly;i++)
- for(j=1000;j>0;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
- 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
-
- //---------打开相应外设时钟--------------------
- RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //使能APB2外设的GPIOC的时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE); //复用功能时钟开启
- }
- /*******************************************************************************
- * Function Name : GPIO_Configuration
- * Description : 初始化GPIO外设
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
- //由电路图可知;配置PC10,PC11引脚
- void GPIO_Configuration(void)
- {
- //CLK:PB5 CLR:PE11 DATA:PE10
- GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //选择PB.1-
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //输出模式为 "复用推挽输出"
- GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOB寄存器
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 |GPIO_Pin_11 ; //选择PE.10 PE.11
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //输出模式为 "浮空输入"
- GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIOE寄存器
-
- //开启时钟 必须在RCC_Configuration中设置
-
-
- //端口重映射:PC10/PC11
- GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);
- }
- void USART3_Configuration(void)
- {
- USART_InitTypeDef USART_InitStructure;
- USART_InitStructure.USART_BaudRate = 9600;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_Parity = USART_Parity_No;
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
- USART_Init(USART3, &USART_InitStructure);
- USART_Cmd(USART3, ENABLE); //开启使能
- }
- /***********************************************************
- name: fputc *
- Description:重定向这个c库printf函数,文件流--->串口USART *
- *
- ************************************************************/
- int fputc(int ch,FILE *f)
- {
- //ch发送给USART1
- USART_SendData(USART3, ch);
- //等待发送完毕
- while(USART_GetFlagStatus(USART3, USART_FLAG_TC)==RESET)
- ;
- return ch;
- }
复制代码
|