本帖最后由 warship 于 2018-7-29 22:30 编辑
有不少初学者对delay_init()函数犯晕,但每一个程序都绕不开,由于原子的例程里因为想兼容操作系统,搞了很多的宏条件,也难怪初学者难以读懂,
其实不光是初学者,说实在的,我没有用到OS,看着这个函数也头大(其实也是没有完全搞懂)
这两天看了一下,撇开对OS的支持(我想绝大多数的STM32初学者都不会上来就用OS的),
这个函数可以简单到只有两行。如下即可:
void delay_init(void)
{
SysTick->LOAD=9000-1; //装载值设定为9*1000-1=8999 即每ms中断一次
SysTick->CTRL|=3; //开启SYSTICK并允许中断
}
怎么样,简单吧?
你用它替换掉原子的函数,我保证能用。
楼下我会详细解释一下.
哦,对了,
忘记提示一句: 使用库函数编程的同学,也是一样可用的。
直接替换掉原函数就可以了。
其实使用库函数编程还是有优势的,看到寄存器编的代码可以直接拿来就用,
而使用寄存器编程的同学,临时想调用库函数就真的不是那么容易了,哈哈。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
谢谢指教,硬件是死的,人是活的,我3楼提供的延时函数可轻松达到5分钟以上
完全改写自库函数SystemInit的版本(备查)
void delay_init(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/*!< RCC 系统复位(调试目的) */
/*!< Set HSION bit */
/*内部高速时钟使能*/
RCC->CR |= (uint32_t)0x00000001;
/*!< 复位 SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], ADCPRE[1:0] 及 MCO[2:0] 等BIT位 */
/*!<HIS被选作系统时钟,SYSCLK(系统时钟)未被分频,低速、高速总线时钟未被分频,ADC时钟被2分频,微控制器无时钟输出*/
RCC->CFGR &= (uint32_t)0xF8FF0000;
/*!< 复位 HSEON, CSSON 及 PLLON 位 */
/* PLL锁相环失能,CSS时钟安全系统失能,外部高速时钟失能*/
RCC->CR &= (uint32_t)0xFEF6FFFF;
/*!< 复位 HSEBYP */
/*清外部时钟可用标志*/
RCC->CR &= (uint32_t)0xFFFBFFFF;
/*!< 复位 PLLSRC, PLLXTPRE, PLLMUL[3:0] 及 USBPRE 等BIT位 */
/* USB时钟为PLL 1.5分频,PLL倍频参数X2,HSE未被分频,HSI震荡时钟/2被当作PLL输入时钟 */
RCC->CFGR &= (uint32_t)0xFF80FFFF;
/*!使能所有时钟中断*/
RCC->CIR = 0x00000000;
/*!< 配置系统时钟频率, 系统总线(HCLK)与可编程时钟(PCLK)1、2 */
/*!< 配置闪存延迟周期,使能预取缓存 */
/*!< SYSCLK, HCLK, PCLK2 及 PCLK1 配置 ---------------------------*/
/*!< 使能 HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
#define HSEStartUp_TimeOut ((uint16_t)0x0500) /*!< HSE启动超时长度定义 */
/*!< 等待 HSE 就绪,超时也跳出本循环 */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
//到这里有两种情况: 一是HSE就绪,即HSEStatus为1;二是HSEStatus为0但超时
if ((RCC->CR & RCC_CR_HSERDY) != RESET) //进一步确认HSE已就绪,置HSEStatus为1;
{
HSEStatus = (uint32_t)0x01;
}
else //HSE未就绪(超时),置HSEStatus为0;
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01) //在确认HSE已就绪的情况下,则:
{
/*!< 使能预取缓存 */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/*!< Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/*!< HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/*!< PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/*!< PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
/*!< PLLCLK = 8MHz * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9);
/*!< 使能 PLL */
RCC->CR |= RCC_CR_PLLON;
/*!< 等待 PLL 就绪 */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/*!< 选择 PLL 作为系统时钟源 */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/*!< 等待PLL 被用作系统时钟源成功 */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
SysTick->LOAD=9000-1; //装载值设定为9*1000-1=8999 即每ms中断一次
SysTick->CTRL|=3; //开启SYSTICK并允许中断
}
else //HSE未就绪,等待超时(即上述第二种情况)
{ /*!< 如果外部高速时钟失败,应用程序就会出现时钟配置错误,用户可在此添加代码处理这种错误 */
/*!< 进入死循环 */
while (1)
{
}
}
}
一周热门 更多>