OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2309|回复: 10

关于选择系统时钟

[复制链接]

55

主题

151

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
304
金钱
304
注册时间
2018-3-12
在线时间
53 小时
发表于 2018-9-16 20:57:38 | 显示全部楼层 |阅读模式
1金钱

以下摘自system_stm32f10x.c
背景是:按照这个文件的执行是采用外部HSE 8M最终通过一系列寄存器操作得到72MHZ的系统时钟;
我现在想尝试的是作为学习了解,在原先的基础上:
1、使用内部HSI为默认的时钟源,最终给系统时钟为48Mhz
方法是:将如下代码的“HSE”统统变为“HSI”,然后再修改下面的分(倍)频系数就可以得到外设需要的时钟频率
这样对吗?不对的话基于这个系统文件怎么修改,具体修改哪几处?

#elif defined SYSCLK_FREQ_48MHz
/**
  * @brief  Sets System clock frequency to 48MHz and configure HCLK, PCLK2
  *          and PCLK1 prescalers.
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
static void SetSysClockTo48(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/   
  /* Enable HSE */   
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);

  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  if (HSEStatus == (uint32_t)0x01)
  {
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* Flash 1 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;   

    /* 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;

#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */

    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);

    /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }


    /* PLL configuration: PLLCLK = PREDIV1 * 6 = 48 MHz */
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
                            RCC_CFGR_PLLMULL6);
#else   
    /*  PLL configuration: PLLCLK = HSE * 6 = 48 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6);
#endif /* STM32F10X_CL */

    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }

    /* Select PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;   

    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock
         configuration. User can add here some code to deal with this error */
  }
}

最佳答案

查看完整内容[请看2#楼]

主程序上来就调用我的delay_init()一切搞定, 不管你用不用systemInit(),反正我是不用。 即使你用了也没有关系, 后来居上的, 调用我的,一切从0开始,懂吗? RCC->CR |= 0x00000001; //使能内部高速时钟HSION [/backcolor] 这不就选择了时钟源为HSI了吗?[/backcolor]
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4522
金钱
4522
注册时间
2018-5-11
在线时间
947 小时
发表于 2018-9-16 20:57:39 | 显示全部楼层
本帖最后由 warship 于 2018-9-16 21:32 编辑
蓝野先生 发表于 2018-9-16 21:21
你要搞清楚,使用systemInit()默认的是外部晶振,不是内部的,首先第一步你就没有完成,你通过什么操作 ...

主程序上来就调用我的delay_init()一切搞定,
不管你用不用systemInit(),反正我是不用。
即使你用了也没有关系,
后来居上的,
调用我的,一切从0开始,懂吗?
RCC->CR |= 0x00000001;     //使能内部高速时钟HSION  
这不就选择了时钟源为HSI了吗?
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4522
金钱
4522
注册时间
2018-5-11
在线时间
947 小时
发表于 2018-9-16 21:12:00 | 显示全部楼层
这样恐怕不行的哦(我看这大堆函数头疼,也不想看)
何必跟这些系统文件较劲呢?这样,水平也难以提高的。
其实要达到你的要求很简单,
就是采用HSI,为8M内部RC振荡器,看时钟图它到PLL是内部二分频为4M,
要想用48M,经过PLL,设为12倍频就可以了。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4522
金钱
4522
注册时间
2018-5-11
在线时间
947 小时
发表于 2018-9-16 21:18:11 | 显示全部楼层
本帖最后由 warship 于 2018-9-16 21:57 编辑

把我的代码修改一下,连系统初始化、延时函数初始化、SYSTICK设为1ms节拍就都有了。

void delay_init(void)
{
RCC->APB1RSTR = 0x00000000;//复位                        
RCC->APB2RSTR = 0x00000000;
         
RCC->AHBENR = 0x00000014;  //睡眠模式闪存和SRAM时钟使能.其他关闭.         
RCC->APB2ENR = 0x00000000; //外设时钟关闭.                           
RCC->APB1ENR = 0x00000000;   
RCC->CR |= 0x00000001;     //使能内部高速时钟HSION                                                                                                                                 
RCC->CFGR &= 0xF8FF0000;   //复位时钟配置                                         
RCC->CR &= 0xFEF6FFFF;     //复位HSEON,CSSON,PLLON
RCC->CR &= 0xFFFBFFFF;     //复位HSEBYP                     
RCC->CFGR &= 0xFF80FFFF;   //复位PLL等
RCC->CIR = 0x00000000;     //关闭所有中断
SCB->VTOR= 0x08000000;     //设置向量表位置,如从RAM启动则为0x20000000

RCC->CFGR=0X00000400; //配置各条总线时钟 APB1=DIV2;APB2=DIV1;AHB=DIV1;
RCC->CFGR|=10<<18;   //设置PLL值为12倍频,得到48M

RCC->CR|=0x01000000;  //打开PLL
while(!(RCC->CR>>25));//等待PLL锁定
RCC->CFGR|=0x00000002;//PLL作为系统时钟
while((RCC->CFGR & 0x0C)!=8); //等待PLL作为系统时钟设置成功         
SysTick->LOAD=6000-1;    //装载值设定为6*1000-1=5999  即每ms中断一次
SysTick->CTRL|=3;        //开启SYSTICK并允许中断
}
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

55

主题

151

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
304
金钱
304
注册时间
2018-3-12
在线时间
53 小时
 楼主| 发表于 2018-9-16 21:21:51 | 显示全部楼层
warship 发表于 2018-9-16 21:12
这样恐怕不行的哦(我看这大堆函数头疼,也不想看)
何必跟这些系统文件较劲呢?这样,水平也难以提高的。 ...

你要搞清楚,使用systemInit()默认的是外部晶振,不是内部的,首先第一步你就没有完成,你通过什么操作选定你的时钟源?
回复

使用道具 举报

55

主题

151

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
304
金钱
304
注册时间
2018-3-12
在线时间
53 小时
 楼主| 发表于 2018-9-16 21:31:40 | 显示全部楼层
warship 发表于 2018-9-16 21:18
把我的代码修改一下,连系统初始化、延时函数初始化、SYSTICK设为1ms节拍就都有了。

void delay_init(vo ...

再次看到你的回复,非常感谢,你的这种方案有效(需要我细细研读技术手册。我知道这种对于血学习掌握单片的本质有帮助,但是需要我细细去配置);你看看我的思路可行吗?

省去了寄存器的操作,只需要看懂这个文件结构,然后选择需要的系统频率,接着根据宏定义的条件编译,进行到对应的函数里对各个时钟源进行选择,然后修改分频系数或者倍频系数,就可完整方便的将这个文件变为自己需要的系统时钟初始话


回复

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4522
金钱
4522
注册时间
2018-5-11
在线时间
947 小时
发表于 2018-9-16 21:34:58 | 显示全部楼层
蓝野先生 发表于 2018-9-16 21:31
再次看到你的回复,非常感谢,你的这种方案有效(需要我细细研读技术手册。我知道这种对于血学习掌握单片 ...

你难道不觉得你上面的更复杂吗?
难道不是一大堆的针对寄存器进行操作吗?
你要把这些读懂,
还不如读懂我的代码了。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4522
金钱
4522
注册时间
2018-5-11
在线时间
947 小时
发表于 2018-9-16 21:45:32 | 显示全部楼层
蓝野先生 发表于 2018-9-16 21:31
再次看到你的回复,非常感谢,你的这种方案有效(需要我细细研读技术手册。我知道这种对于血学习掌握单片 ...

另外,说一点,
即使你是使用库函数进行编程的,
千万不要排斥对寄存器的操作。
原因寄存器的操作是不需要引用任何库文件的,
所以与你的程序结构不会有附加要求,与库函数编程是完美兼容的。
凡是寄存器的操作,直接抄过来就行了,
天下文章一大抄,看你会抄不会抄了。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

55

主题

151

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
304
金钱
304
注册时间
2018-3-12
在线时间
53 小时
 楼主| 发表于 2018-9-16 21:46:03 | 显示全部楼层
warship 发表于 2018-9-16 21:12
这样恐怕不行的哦(我看这大堆函数头疼,也不想看)
何必跟这些系统文件较劲呢?这样,水平也难以提高的。 ...

请问你是这样操作过,还是做出的猜测?
“就是采用HSI,为8M内部RC振荡器”就是我问的第一个问题,你通过什么操作来选择HSI?
回复

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4522
金钱
4522
注册时间
2018-5-11
在线时间
947 小时
发表于 2018-9-16 21:47:25 | 显示全部楼层
蓝野先生 发表于 2018-9-16 21:46
请问你是这样操作过,还是做出的猜测?
“就是采用HSI,为8M内部RC振荡器”就是我问的第一个问题,你通 ...

RCC->CR |= 0x00000001;     //使能内部高速时钟HSION  
这不就选择了时钟源为HSI了吗?
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复

使用道具 举报

55

主题

151

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
304
金钱
304
注册时间
2018-3-12
在线时间
53 小时
 楼主| 发表于 2018-9-17 08:25:46 | 显示全部楼层
warship 发表于 2018-9-16 21:25
主程序上来就调用我的delay_init()一切搞定,
不管你用不用systemInit(),反正我是不用。
即使你用了 ...

懂你的意思,受教了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-20 05:56

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表