历史上的今天
返回首页

历史上的今天

今天是:2025年08月19日(星期二)

正在发生

2018年08月19日 | 使用内部的MSI振荡器给STM32L476RG单片机提供80MHz的时钟

2018-08-19 来源:eefocus

#include

#include

 

// 1<=nus<=13107

void delay_us(uint16_t nus)

{

if ((RCC->APB1ENR2 & RCC_APB1ENR2_LPTIM2EN) == 0)

{

RCC->APB1ENR2 |= RCC_APB1ENR2_LPTIM2EN;

LPTIM2->CFGR = 4 << LPTIM_CFGR_PRESC_Pos; // 80MHz/16=5MHz

LPTIM2->CR = LPTIM_CR_ENABLE;

}

LPTIM2->ARR = nus * 5 - 1;

LPTIM2->CR |= LPTIM_CR_SNGSTRT;

while ((LPTIM2->ISR & LPTIM_ISR_ARRM) == 0);

LPTIM2->ICR = LPTIM_ICR_ARRMCF;

}

 

int fputc(int ch, FILE *fp)

{

if (fp == stdout)

{

if (ch == '\n')

{

while ((USART2->ISR & USART_ISR_TXE) == 0);

USART2->TDR = '\r';

}

while ((USART2->ISR & USART_ISR_TXE) == 0);

USART2->TDR = ch;

}

return ch;

}

 

void set_clock(void)

{

RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN;

PWR->CR1 |= PWR_CR1_DBP; // 允许访问备用区域寄存器

// 打开LSE

if ((RCC->BDCR & RCC_BDCR_LSEON) == 0)

{

RCC->BDCR |= RCC_BDCR_LSEON;

while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0); // 等待LSE稳定

}

RCC->CR |= RCC_CR_MSIPLLEN; // MSI使用LSE校准MSI

// 配置PLL: MSI/M*N/R=4MHz/1*40/2=80MHz

RCC->PLLCFGR = RCC_PLLCFGR_PLLREN | (40 << RCC_PLLCFGR_PLLN_Pos) | RCC_PLLCFGR_PLLSRC_MSI;

RCC->CR |= RCC_CR_PLLON;

while ((RCC->CR & RCC_CR_PLLRDY) == 0); // 等待PLL稳定

// 根据参考手册3.3.3 Read access latency, Table 11. Number of wait states according to CPU clock (HCLK) frequency

// CPU时钟要达到64MHz以上, LATENCY必须为4WS

// 由PWR_CR1_VOS可知当前V_CORE为Range 1 (最高时钟频率80MHz)

FLASH->ACR |= FLASH_ACR_LATENCY_4WS; // 参阅: Increasing the CPU frequency

while ((FLASH->ACR & FLASH_ACR_LATENCY) != FLASH_ACR_LATENCY_4WS);

// 将PLL选作系统时钟

RCC->CFGR |= RCC_CFGR_SW;

while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS);

// 刚开始MSI还没有校准, 所以使用115200波特率时必须要延时, 否则前四个字符会乱码

// 延时5个字节的时间, 每个字节69.4us, 共347us

delay_us(347);

// 使用9600波特率时, 发送一个字符就要833.3us, 远远大于这个时间, 所以无需延时

}

 

int main(void)

{

set_clock();

// LED灯配置

RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;

GPIOA->MODER &= ~GPIO_MODER_MODE5_1;

GPIOA->BSRR = GPIO_BSRR_BS5; // LED灯亮

// 配置串口2

RCC->APB1ENR1 |= RCC_APB1ENR1_USART2EN;

GPIOA->AFR[0] = 7 << GPIO_AFRL_AFSEL2_Pos;

GPIOA->MODER &= ~GPIO_MODER_MODE2_0;

//GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED2;

USART2->BRR = 80000000 / 115200; // 被除数为时钟频率, 除数为波特率

USART2->CR1 = USART_CR1_UE | USART_CR1_TE;

printf("ABCDEFGH\n");

printf("PWR->CR1=0x%08x\n", PWR->CR1);

printf("RCC->BDCR=0x%08x\n", RCC->BDCR);

printf("RCC->CFGR=0x%08x\n", RCC->CFGR);

printf("RCC->CR=0x%08x\n", RCC->CR);

printf("RCC->PLLCFGR=0x%08x\n", RCC->PLLCFGR);

printf("USART2->BRR=%d\n", USART2->BRR);

GPIOA->BRR = GPIO_BRR_BR5; // LED灯灭

while (1);

}

MSI晶振接到PLL上后会通过外部的LSE晶振进行自动校准。校准期间,不精准的MSI时钟频率被PLL放大之后就会显著地影响串口的时钟,导致串口字符乱码,因此时钟切换后串口发送第一个字符之前必须延时,等待MSI时钟校准。


解决串口乱码问题还有一个更简单的方法,无需延时。单片机内部还带有一个16MHz的HSI时钟,在RCC->CCIPR寄存器中将USART2的时钟由与MSI有关的APB1时钟切换到HSI时钟,就能彻底解决问题。


【程序2】


#include

#include

 

int fputc(int ch, FILE *fp)

{

if (fp == stdout)

{

if (ch == '\n')

{

while ((USART2->ISR & USART_ISR_TXE) == 0);

USART2->TDR = '\r';

}

while ((USART2->ISR & USART_ISR_TXE) == 0);

USART2->TDR = ch;

}

return ch;

}

 

void set_clock(void)

{

RCC->APB1ENR1 |= RCC_APB1ENR1_PWREN;

PWR->CR1 |= PWR_CR1_DBP; // 允许访问备用区域寄存器

// 打开LSE

if ((RCC->BDCR & RCC_BDCR_LSEON) == 0)

{

RCC->BDCR |= RCC_BDCR_LSEON;

while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0); // 等待LSE稳定

}

RCC->CR |= RCC_CR_MSIPLLEN; // MSI使用LSE校准MSI

// 配置PLL: MSI/M*N/R=4MHz/1*40/2=80MHz

RCC->PLLCFGR = RCC_PLLCFGR_PLLREN | (40 << RCC_PLLCFGR_PLLN_Pos) | RCC_PLLCFGR_PLLSRC_MSI;

RCC->CR |= RCC_CR_PLLON;

while ((RCC->CR & RCC_CR_PLLRDY) == 0); // 等待PLL稳定

// 根据参考手册3.3.3 Read access latency, Table 11. Number of wait states according to CPU clock (HCLK) frequency

// CPU时钟要达到64MHz以上, LATENCY必须为4WS

// 由PWR_CR1_VOS可知当前V_CORE为Range 1 (最高时钟频率80MHz)

FLASH->ACR |= FLASH_ACR_LATENCY_4WS; // 参阅: Increasing the CPU frequency

while ((FLASH->ACR & FLASH_ACR_LATENCY) != FLASH_ACR_LATENCY_4WS);

// 将PLL选作系统时钟

RCC->CFGR |= RCC_CFGR_SW;

while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS);

}

 

int main(void)

{

set_clock();

// LED灯配置

RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;

GPIOA->MODER &= ~GPIO_MODER_MODE5_1;

GPIOA->BSRR = GPIO_BSRR_BS5; // LED灯亮

// 配置串口2

RCC->APB1ENR1 |= RCC_APB1ENR1_USART2EN;

GPIOA->AFR[0] = 7 << GPIO_AFRL_AFSEL2_Pos;

GPIOA->MODER &= ~GPIO_MODER_MODE2_0;

//GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED2;

// 使用HSI16作为USART2的时钟可以避免乱码

RCC->CR |= RCC_CR_HSION;

while ((RCC->CR & RCC_CR_HSIRDY) == 0);

RCC->CCIPR = RCC_CCIPR_USART2SEL_1; // HSI16作为USART2的时钟

USART2->BRR = 16000000 / 115200; // 被除数为时钟频率, 除数为波特率

USART2->CR1 = USART_CR1_UE | USART_CR1_TE;

printf("ABCDEFGH\n");

printf("PWR->CR1=0x%08x\n", PWR->CR1);

printf("RCC->BDCR=0x%08x\n", RCC->BDCR);

printf("RCC->CFGR=0x%08x\n", RCC->CFGR);

printf("RCC->CR=0x%08x\n", RCC->CR);

printf("RCC->PLLCFGR=0x%08x\n", RCC->PLLCFGR);

printf("USART2->BRR=%d\n", USART2->BRR);

GPIOA->BRR = GPIO_BRR_BR5; // LED灯灭

while (1);

}


推荐阅读

史海拾趣

Fenghua (HK) Electronics Ltd公司的发展小趣事

作为一家有社会责任感的企业,Fenghua (HK) Electronics Ltd积极履行社会责任,关注环保和公益事业。公司采用了环保材料和节能技术,降低了生产过程中的能耗和排放。同时,公司积极参与社会公益活动,为当地社区和教育事业做出了积极贡献。这些举措不仅提升了公司的社会形象,也为企业的可持续发展奠定了坚实基础。

请注意,以上故事框架仅供参考,你可以根据Fenghua (HK) Electronics Ltd公司的实际情况和发展历程进行进一步的拓展和完善。

AXSEM公司的发展小趣事

为了降低成本、提高生产效率,Fenghua (HK) Electronics Ltd不断优化供应链管理。公司与供应商建立了长期稳定的合作关系,实现了原材料的及时供应和成本控制。同时,公司引入了先进的生产管理系统,对生产过程中的各个环节进行精细化管理,确保了产品质量的稳定性和一致性。

ARRA Inc公司的发展小趣事

Fenghua (HK) Electronics Ltd自成立以来,始终将技术创新作为企业发展的核心动力。公司投入大量研发资源,不断推出具有市场竞争力的新产品。其中,一款具有自主知识产权的智能家居控制系统,凭借其独特的智能化和便捷性,在市场上引起了广泛关注。公司通过与国内外知名科技企业的合作,不断引进先进技术和管理经验,提升了整体竞争力。

General Instrument Corp公司的发展小趣事
根据型号不同,提供2到8个输入通道选项,适用于需要多路信号采样的应用场景。
ECS公司的发展小趣事

面对云计算技术的不断发展和市场竞争的加剧,ECS公司制定了面向未来的战略布局。他们将继续加大在研发方面的投入,推动ECS服务的不断升级和创新;同时,他们还将积极探索新的业务领域和市场机会,为客户提供更加全面、丰富的服务。此外,ECS公司还注重可持续发展和社会责任。他们致力于降低能耗和排放、推动绿色计算等方面的工作;同时,他们还积极参与社会公益事业和慈善活动,回馈社会。这些举措使得ECS公司不仅成为了一家领先的云服务提供商,还成为了一家具有社会责任感的企业。

BLT Circuit Services公司的发展小趣事

品质一直是BLT Circuit Services公司的核心竞争力。公司注重品质管理,建立了严格的质量控制体系,从原材料采购到生产过程中的每一个环节都进行严格把关。正是这种对品质的执着追求,使得BLT Circuit Services的产品在行业内赢得了良好的口碑,为公司赢得了大量的忠实客户。

问答坊 | AI 解惑

从51到ARM. 32位嵌入式系统入门

从51到ARM. 32位嵌入式系统入门…

查看全部问答>

求助!FPGA输入语音

各位大侠, 我最近在做一个报告,要求要用FPGA连接耳麦采取声音信号然后处理 储存。 真是万事开头难啊,刚开始就卡住了 无从下手。 希望大侠们给点建议。多谢了! 有相关研究的同仁们可以加我izhangdan@gmail.com  希望在这方面有所长 ...…

查看全部问答>

如何和mirror driver 通信

写了一个mirror driver, 我想用share memory方式和app通信。 但出了个问题,create sharememory需要app进程的上下文。 我想是用createfile提供,但mirror driver如何提供设备连接名呢? 不知这种方式是否可行,如不行,还有别的办法吗? 还有 ...…

查看全部问答>

Wince如何订制taskbar?

        为了能捕捉到有程序启动、关闭、激活等消息,我用了以下代码。但这样会存在一个问题,就是打开文件夹时,文件夹里面的内容无法显示。请问是什么原因,或是能用别的什么办法捕捉到程序启动、关闭等消息吗? ...…

查看全部问答>

关于RegQueryValueEx操作问题

关于RegQueryValueEx操作问题 LPBYTE dwValue;                                 DWORD dwLength = sizeof(DWORD);         i ...…

查看全部问答>

请教Windriver中WD_MultiTransfer使用方法(内有写好的程序)

以下是自己编写的Windriver开发PCI驱动的程序,目前已经调通,但是dwResult结果不对,跟踪程序结果是00xc3f000e8,但与Windriver的自带程序读同一地址所得到的结果086300A2不同。请问问题出现在哪里? 我想认识开发Windriver的朋友们,我QQ号码:819 ...…

查看全部问答>

阿牛哥八月份第三周工作汇报

     阿牛哥和同事们第三周着力推智能电表和安防矩阵产品方案,看看贸易商和代理商业务运营模式还是有很大区别的。 情报搜集,重点扫荡。中标电表客户还有中标安防监控工程上游制造商机会最大,一一联系。涉及太多商业机密和 ...…

查看全部问答>

开发板资料大搜集(即日起到2月28日),精美礼物等你拿!

对于想学习和正在学习单片机和嵌入式的你来说,最想拥有的是什么?我想可能是一块资源丰富、功能强大、资料齐全的开发板!!!   目前市场上各种各样的单片机和嵌入式系统开发板可谓是琳琅满目,价格也是高低不等,每一种芯片的开发板都有各 ...…

查看全部问答>

重映射后,SPI3与SPI1共用了PA4,这两个SPI能正常使用么?

                                 在stm32F107里,重映射后,SPI3与SPI1共用了PA4,这两个SPI能正常使用么?有没有什么问题?…

查看全部问答>

TI MaxLife™ 快速充电电源管理芯片介绍

对于开发这些便携式设备的系统和产品设计人员来说,更长的电池寿命是最大挑战之一。 为了帮助解决这一挑战并为设计人员提供显著优势,德州仪器 (TI) 现在推出了两款采用 TI 获得专利的新 MaxLife™ 快速充电技术的电源管理芯片组。 MaxLife 电 ...…

查看全部问答>