历史上的今天
返回首页

历史上的今天

今天是:2024年10月08日(星期二)

正在发生

2018年10月08日 | STM32定时器不准确启动时钟的问题

2018-10-08 来源:eefocus

用STM32 F407IG 开发一硬件控制器,需要精准的定时器。我使用了IIM2,可上电启动。有时候准确,有时候开机

定时器,很慢,比如定时500MS 闪烁一次,可能3秒才闪烁一次。源代码如下。

int main(void)

{

      

GPIO_Configuration();   

  TIM_Config();

  NVIC_TIM_Config();    

  while(1)

{

  

}

}

void GPIO_Configuration(void)  

{

    GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(LED1_RCC_AHBPeriph|LED2_RCC_AHBPeriph|LED3_RCC_AHBPeriph|LE      D4_RCC_AHBPeriph , ENABLE);

 

GPIO_InitStructure.GPIO_Pin = LED1_Pin;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_Init(LED1_Port, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = LED2_Pin;

GPIO_Init(LED2_Port, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = LED3_Pin;

    GPIO_Init(LED3_Port, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = LED4_Pin;

   GPIO_Init(LED4_Port, &GPIO_InitStructure);

}

void TIM_Config(void)

{

   TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

   TIM_DeInit(TIM2);//初始化TIM1寄存器 407IG 主频为 168MHZ   

TIM_TimeBaseStructure.TIM_Period = 10000-1;          

TIM_TimeBaseStructure.TIM_Prescaler =4100-1;     

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数

TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0;

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_ARRPreloadConfig(TIM2, ENABLE); //ARR自动装载默认是打开的,可以不设置 

TIM_ClearFlag(TIM2, TIM_FLAG_Update);

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

TIM_Cmd(TIM2, ENABLE); //使能TIM1定时器

}

 void NVIC_TIM_Config(void)

 {

 

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);           //中断优先级分组为1

NVIC_InitStructure.NVIC_IRQChannel =TIM2_IRQn;  //嵌套中断通道为TIM2

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级为1

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;    //响应优先级为0

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     //使能中断

NVIC_Init(&NVIC_InitStructure);

 }

 void TIM2_IRQHandler(void)

{

   if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)

    {

 TIM_ClearITPendingBit(TIM2,TIM_IT_Update);   

    DispLed(3); 

        

}

    TIM_ClearFlag(TIM2, TIM_FLAG_Update);  

 

}

 void DispLed(uint8_t ln)

 {

     if(ln==2)

{

    Led2++;

         if(Led2==0x2ffff)

     {

    

    GPIO_SetBits(LED2_Port , LED2_Pin);

      }

     else if(Led2==0x4ffff)

     {

    

    GPIO_ResetBits(LED2_Port , LED2_Pin);

     }

 else if(Led2>0x4ffff)

   Led2=0;

  }

  else if(ln==1)

 {

 Led1++;

         if(Led1==10)

     {

    

    GPIO_SetBits(LED1_Port , LED1_Pin);

      }

     else if(Led1==20)

     {     

    GPIO_ResetBits(LED1_Port , LED1_Pin);

     }

 else if(Led1>20)

   Led1=0;

  }

       else if(ln==4)

  {

      if(Led4==0)

     {

    Led4=1;

    GPIO_SetBits(LED4_Port , LED4_Pin);

      }

     else

     {

    Led4=0;

    GPIO_ResetBits(LED4_Port , LED4_Pin);

     }

  }

   else if(ln==3)

  {

      if(Led3==0)

     {

    Led3=1;

    GPIO_SetBits(LED3_Port , LED3_Pin);

      }

     else

     {

    Led3=0;

    GPIO_ResetBits(LED3_Port , LED3_Pin);

     }

  }

 } 

折腾几天,定时就是,有时候准确,有时候特别慢,检查代码,反复比对。没有错误。后考虑,可能启动的系统采用的时钟不对。但,所有的例子程序,F407,都是默认的系统时钟。进一步分析系统启动过程

startup_stm32f4xx.s(系统启动文件)

; Reset handler

Reset_Handler    PROC

                 EXPORT  Reset_Handler             [WEAK]

        IMPORT  SystemInit

        IMPORT  __main

                 LDR     R0, =SystemInit

                 BLX     R0

                 LDR     R0, =__main

                 BX      R0

                 ENDP

在主程序启动之前,调用

//system_stm32f4xx.c

void SystemInit(void)

{

  //设定FPU

  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)

    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  

  #endif

 

 

  RCC->CR |= (uint32_t)0x00000001;   //使能内部时钟

  RCC->CFGR = 0x00000000;               // Reset CFGR register 选择HSI振荡器做系统时钟 16MHZ

  //关闭HSE,关闭时钟安全系统,关闭PLL和PLLI2S

  RCC->CR &= (uint32_t)0xFEF6FFFF;  // Reset HSEON, CSSON and PLLON bits  

  //配置PLLQ=4,选择HSI为PLL和PLLI2S时钟源,PLLP=2,PLLP=192,PLLM=16

  RCC->PLLCFGR = 0x24003010;    

  //HSEBYPASS=0,即外部提供晶体非晶振

  RCC->CR &= (uint32_t)0xFFFBFFFF;     

  //禁止所有中断

  RCC->CIR = 0x00000000;

#ifdef DATA_IN_ExtSRAM

  SystemInit_ExtMemCtl(); 

#endif

         

 

  SetSysClock();

  //设定中断向量表

#ifdef VECT_TAB_SRAM

  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;

#else

  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;

#endif

}

  void SetSysClock(void)

{

  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

     

  // Enable HSE :使能HSE外部时钟

  RCC->CR |= ((uint32_t)RCC_CR_HSEON);

  

//等待HSERDY位准备好(含超时次数检查)

  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;  //准备好,则HSEStatus 为1

  }

  else

  {

    HSEStatus = (uint32_t)0x00;     //否则,HSEStatus 为0

  }

  if (HSEStatus == (uint32_t)0x01) //如果HSEStatus 为1,则表示外部时钟准备好

  {

   

//使能APB1供电,并使VOS=1支持高频

    RCC->APB1ENR |= RCC_APB1ENR_PWREN;

    PWR->CR |= PWR_CR_VOS;

    // HCLK = SYSCLK / 1:HCLK=System Clock(=168MHz)

    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

      

    // PCLK2 = HCLK / 2 (:=84MHz)

    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;

    

     // PCLK1 = HCLK / 4(:=42MHz)

    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

    // Configure the main PLL 配置锁相环

    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |

                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

    // Enable the main PLL 使能PLL和PLLI2S

    RCC->CR |= RCC_CR_PLLON;

   

    while((RCC->CR & RCC_CR_PLLRDY) == 0)

    {

    }

   

    // Configure Flash prefetch, Instruction cache, Data cache and wait state 

//配置FLASH读写时序参数 

    FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

    // Select the main PLL as system clock source 

    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));

    RCC->CFGR |= RCC_CFGR_SW_PLL;

    // Wait till the main PLL is used as system clock source 

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

    {

    }

  }

  else

  { //如果HSEStatus 为0,则表示外部时钟有问题

    //用户可以添加代码处理

  }

}

通过这两个函数分析,可能是系统启动时,当外部时钟准备失败。本来168M的时钟,采用了默认的16M时钟,所以定时变慢了。

尝试在主程序中,重新加载一次,系统时钟设定。

SetSysClock(); 

把这个函数重新定义到#include "system_stm32f4xx.h"

然后在主程序中添加 #include "system_stm32f4xx.h"

搞定。


推荐阅读

史海拾趣

Apex Tool Group公司的发展小趣事

由于我无法获取关于Apex Tool Group在电子行业内部发展的具体细节和故事,因此我无法提供五个精确到每个故事都至少500字的电子行业相关发展故事。但我可以根据已知信息,尝试概括Apex Tool Group的发展概况,以及它如何可能涉及电子行业。

Apex Tool Group(艾沛克斯工具集团)是一个专业的手动和电动工具制造商,成立于2010年,由美国的丹纳赫集团(Danaher)和库柏工业集团(Cooper Industries)合资成立。公司总部位于美国马里兰州的Sparks,并在全球拥有20多家工厂,产品覆盖多个国家和地区。

Apex Tool Group的发展之路充满了变革和机遇。它凭借两大集团的技术和资源优势,迅速崛起为行业内的佼佼者。公司不断推出创新产品,满足不同客户的需求,并在市场上获得了良好的口碑。

在电子行业,Apex Tool Group的产品可能也得到了广泛应用。随着电子行业的快速发展,对高精度、高效率的工具需求日益增长。Apex Tool Group凭借其卓越的技术和品质,为电子行业提供了可靠的工具解决方案。无论是在电子产品的制造过程中,还是在电子设备的维修和维护中,Apex Tool Group的工具都发挥着重要作用。

此外,Apex Tool Group还注重与客户的紧密合作。它根据客户的需求提供定制化服务,帮助客户解决实际问题。这种以客户为中心的经营理念,使得Apex Tool Group在电子行业中赢得了广泛的认可和信任。

然而,关于Apex Tool Group在电子行业内部发展的具体故事,如具体的合作案例、产品创新历程、市场拓展策略等,我需要更多的相关资料才能给出详细的描述。如果您对这方面的信息感兴趣,建议查阅Apex Tool Group的官方网站、行业报告或相关新闻报道,以获取更详细的信息。

希望以上内容能够对您有所帮助,如有更多问题,欢迎继续提问。

Euroquartz公司的发展小趣事

随着全球电子制造产业的不断发展,Euroquartz也积极拓展国际市场。公司凭借其高品质的产品和专业的技术服务,赢得了全球客户的信赖和支持。如今,Euroquartz的产品已经覆盖全球90多个国家和地区,为全球电子制造产业提供了重要的石英晶振、振荡器、滤波器以及其它频率相关产品。

Advanced Milliwave Laboratories Inc公司的发展小趣事

AML深知技术创新是企业发展的核心动力。因此,公司始终坚持自主研发和技术创新,不断推出新的微波产品和技术。这些新产品不仅具有更高的性能和更广泛的应用范围,还进一步提升了AML在微波技术领域的竞争力。同时,AML还注重与高校和研究机构的合作,共同开展技术研发和人才培养,为公司的长远发展提供了有力支持。

Empro Technology Corp公司的发展小趣事

Empro Technology Corp成立于2005年,由一群热衷于电子技术的工程师创立。在初创阶段,公司专注于研发高效能、低功耗的半导体芯片。经过数年的不懈努力,公司成功推出了一款具有颠覆性技术的芯片产品,其性能远超当时市场上的同类产品,迅速获得了市场的认可。

Hitachi (Renesas )公司的发展小趣事

随着全球制造业的转型升级,Empro Technology Corp也积极响应,开始了智能制造的探索和实践。公司引进了先进的生产设备和管理系统,实现了生产过程的自动化和智能化。这不仅提高了生产效率,也保证了产品质量和稳定性。

BH Electronics公司的发展小趣事

BH Electronics的创立源于创始人李明对电子技术的深厚兴趣和敏锐洞察。在20世纪90年代初,电子市场刚刚起步,李明凭借对市场的精准判断,决定投身于这一新兴行业。他带领一支小团队,在简陋的办公室中开始了艰苦的创业历程。他们昼夜兼程,研发出了一款具有竞争力的电子元件,成功打开了市场的大门。虽然初期资金匮乏,市场认可度低,但李明和他的团队凭借坚韧不拔的精神,逐步在市场中站稳了脚跟。

问答坊 | AI 解惑

数字信号处理教程

数字信号处理教程[][][]…

查看全部问答>

功率晶体管、RF MEMS和振荡器的技术进展

微波产业尽管在持续创新,许多产品仍根植于相同技术。例如,砷化镓(GaAs)就是目前许多先进功放及其它有源器件的核心技术。但在这些现象中,孕育着可能变革许多产品制造方式方法的创新。这些“颠覆性技术”会以闻所未闻、见所未见的完全新奇的面目兴 ...…

查看全部问答>

电子天平用于试验中

电子天平将聚氨酯软泡裁成长宽高均为50mm的形状,按40%的比例将阻燃剂分别溶解在蒸馏水中,将聚氨酯软泡放入上述溶液中,挤压浸泡约10min,挤掉多余的溶液,放入烘箱中在100℃的情况下进行烘干。将聚氨酯软泡空白样品剪成碎末,用电子天平称取大约5m ...…

查看全部问答>

uclinux的内核 大家一般都裁剪到多小?

今天一个家伙对我说 他同事 裁剪带有网络功能的uclinux 到 300多KB. 不带网络功能的 170多KB. 来自EEWORLD合作群:arm linux fpga 嵌入0(49900581) 群主:wangkj…

查看全部问答>

c51中递归调用如何使用?

我写了一个小程序,在c51中编译结果总是0,我知道是变量覆盖问题,但我不知道如何去写,请教大虾!!! #include int factorial( int n); int factorial( int n) { int result; if(n == 0)         result=1; else &n ...…

查看全部问答>

编译了UART例子

bin   97,012 字节经过了很多步骤,终于成功编译,生成bin文件97,012 字节USARTExample2 Use the USART1 interrupts to communicate with the hyperterminal. fi ...…

查看全部问答>

香水版主,请问有STM32内的D/A的详细指标吗?

                                 比如更新速率、积分非线性、微分非线性、增益误差、偏移误差和温度系数,我在ST网上的资料上没有发现这些,请指教 ...…

查看全部问答>

菜虫请教:stm32的定时器与外部中断的问题

请问stm32定时器输入捕获模式下的中断与外部中断有什么区别?都是捕捉到信号的边沿之后执行中断程序啊…

查看全部问答>

恒流源的应用教程

      恒流源就是一个能输出恒定电流的电源。 恒流源的应用领域非常广阔,然而不少应该用恒流源供电的场合,不适当的使用了稳压电源。下面举一些实际例子来说明恒流源的应用:   1:电真空器件,如示波管、显像管 ...…

查看全部问答>