MCU(RealTek)系统时钟及1ms中断设定

合集下载

STM32系列MCU硬件实时时钟(RTC)应用笔记说明书

STM32系列MCU硬件实时时钟(RTC)应用笔记说明书

2017年6月Doc ID 018624 Rev 1 [English Rev 5]1/45AN3371应用笔记在 STM32 F0、F2、F3、F4 和 L1 系列MCU 中使用硬件实时时钟(RTC )前言实时时钟 (RTC) 是记录当前时间的计算机时钟。

RTC 不仅应用于个人计算机、服务器和嵌入式系统,几乎所有需要准确计时的电子设备也都会使用。

支持 RTC 的微控制器可用于精密计时器、闹钟、手表、小型电子记事薄以及其它多种设备。

本应用笔记介绍超低功耗中等容量、超低功耗大容量、F0、F2和 F4 系列器件微控制器中嵌入式实时时钟 (RTC) 控制器的特性,以及将 RTC 用于日历、闹钟、定时唤醒单元、入侵检测、时间戳和校准应用时所需的配置步骤。

本应用笔记提供了含有配置信息的示例,有助于您快速准确地针对日历、闹钟、定时唤醒单元、入侵检测、时间戳和校准应用配置 RTC 。

注:所有示例和说明均基于 STM32L1xx 、STM32F0xx 、STM32F2xx 、STM32F4xx 和STM32F3xx 固件库,以及 STM32L1xx (RM0038)、STM32F0xx (RM0091)、STM32F2xx (RM0033)、STM32F4xx (RM0090)、STM32F37x (RM0313) 和 STM32F30x(RM0316) 的参考手册。

本文提到的STM32 指超低功耗中等容量、超低功耗大容量、F0、F2 和 F4 系列器件。

超低功耗中等 (ULPM) 容量器件包括 STM32L151xx 和 STM32L152xx 微控制器,Flash 容量在 64 KB 到 128 KB 之间。

超低功耗大 (ULPH) 容量器件包括 STM32L151xx 、STM32L152xx 和 STM32L162xx 微控制器,Flash 容量为 384 KB 。

F2 系列器件包括 STM32F205xx 、STM32F207xx 、STM32F215xx 和 STM32F217xx 微控制器。

STM系列微控制器的中断控制和中断优先级设置

STM系列微控制器的中断控制和中断优先级设置

STM系列微控制器的中断控制和中断优先级设置中断控制是现代微控制器中一个非常重要的功能,它允许微控制器在执行主循环任务时能够及时响应外部事件。

STMicroelectronics(简称STM)系列微控制器在中断控制和中断优先级设置方面提供了丰富的功能和灵活性。

在STM系列微控制器中,中断控制是通过NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)来完成的。

NVIC是一种高级中断控制器,它支持多个中断源,并且可以按照优先级依次处理这些中断。

中断的触发可以是外部事件,比如按键的按下、定时器的溢出等;也可以是内部事件,比如某个寄存器的值达到某种条件、DMA传输完成等。

当中断事件发生时,微控制器会立即转入中断服务程序(ISR,Interrupt Service Routine)中执行相应的处理,处理完成后再返回到主循环任务。

在STM系列微控制器中,中断的触发可以配置为边沿触发或电平触发。

边沿触发是指只在中断事件发生或结束的瞬间触发中断;电平触发是指只要中断事件为真,中断就一直触发。

中断的优先级设置是为了解决多个中断事件同时发生时的处理顺序问题。

STM系列微控制器提供了16级中断优先级,优先级为0的中断最高,优先级为15的中断最低。

当多个中断事件同时发生时,中断控制器会自动将当前正在执行的中断挂起,然后执行优先级更高的中断。

当优先级更高的中断处理完成后,中断控制器会根据优先级恢复之前挂起的中断,从而实现中断的优先级控制。

中断优先级的设置在编程中是非常重要的,它直接影响到系统的响应速度和可靠性。

一般来说,高优先级的中断应该优先处理那些对实时性要求较高的事件,而低优先级的中断则用于处理一些非实时性的事件。

当然,在具体的应用中,中断优先级的设置要根据实际需求和中断事件的特性来决定。

在STM系列微控制器中,中断控制和中断优先级设置的编程步骤如下:1. 配置中断触发方式。

PIC32MZ系列MCU的定时器测试学习教程

PIC32MZ系列MCU的定时器测试学习教程

PIC32MZ 系列MCU 的定时器测试学习教程
前面说过TC1 使用的是外部32K 的时钟源,因为这个晶振没有焊接,无
法测试,所以我们这里选择的测试时钟为TC2。

本MCU 一共有9 个定时器,TC1-TC9,都是16 位的。

先来看看时钟内
部框图,TC 外设使用的是PBCLK3,频率是100MHZ
打开MHC,选择Harmony Framework Configuration》Drivers》Timer 进行设置,下面大体介绍下每个设置的含义
1,Driver Implementation:这个有动态和静态的可以,我们这里选择动态的,具体的区别在下一篇中介绍
2,中断模式选择使能,这里打钩,表示使能中断。

3,Timer Module ID:选择ID2,就是使用的TC2,这里可以选择1-9,但1 的时钟源没有,所以只能选择2-9,我们选择2 来测试。

单片机的延时与中断问题及解决方法

单片机的延时与中断问题及解决方法

单片机的延时与中断问题及解决方法概述在单片机的应用开发中,延时和中断是两个非常重要的概念。

延时是指在程序中暂停一段时间,而中断是指在程序执行过程中突然打断当前的执行流程去处理其他事务。

延时和中断的使用对于单片机的应用开发非常重要,合理的使用可以提高程序的效率和可靠性。

在实际开发中,延时和中断也经常会遇到一些问题。

本文将针对单片机的延时和中断问题进行分析,并提出相应的解决方法。

延时问题及解决方法延时是指在程序执行过程中暂停一段时间。

单片机中常用的延时方法有软件延时和硬件延时两种。

软件延时是通过在程序中执行循环来实现延时的。

例如:void delay(unsigned int time){while(time--);}硬件延时是通过单片机内部的定时器来实现延时的。

在51单片机中可以通过配置定时器的初值和工作模式来实现延时。

在实际开发中,延时经常会遇到一些问题。

延时时间不准确,延时过长或过短等。

造成这些问题的原因有很多,常见的原因包括系统时钟频率不准确、程序执行过程中被中断打断、延时中使用了未初始化的变量等。

为了解决这些问题,可以采取一些措施。

要确保系统时钟频率的准确性。

一般来说,单片机的延时是通过系统时钟来实现的,如果系统时钟频率不准确,那么延时时间也会不准确。

要确保系统时钟频率的准确性。

一种简单的方法是通过外部晶振来提供时钟信号,另一种方法是通过软件校准系统时钟频率。

要避免在延时中使用未初始化的变量。

在C语言中,未初始化的变量的值是不确定的,因此在延时中使用未初始化的变量可能会导致延时时间不准确。

在延时前要确保所使用的变量已经正确初始化。

要避免在延时中被中断打断。

在单片机的程序执行过程中,可能会发生各种中断事件,如果在延时中被中断打断,那么延时时间也会不准确。

为了避免这种情况,可以在延时前禁止所有中断,延时结束后再使能中断。

中断问题的解决方法主要包括中断优先级的设置、中断屏蔽和中断标志的清除。

中断优先级的设置是非常重要的。

单片机的延时与中断问题及解决方法

单片机的延时与中断问题及解决方法

单片机的延时与中断问题及解决方法在单片机的程序中,常常会遇到延时和中断的问题。

延时是指在程序中需要暂时停顿一段时间,而中断是指在程序执行过程中突然发生的事件,需要立即处理。

一、延时问题:单片机中的CPU速度非常快,一条指令可以在几十甚至几百纳秒内执行完毕。

在需要进行延时的情况下,不能直接使用空指令来实现延时,否则延时的时间将会非常短暂。

解决延时问题的方法如下:1. 软件延时:将一个循环执行的空指令放在一个循环中,通过多次执行该循环来实现延时。

这种方法实现简单,但由于CPU速度非常快,必须通过增加空指令的执行次数来实现较长的延时时间,不适用于需要精确延时的场合。

2. 硬件延时:通过外接的计时器或计数器来实现延时。

这种方法可以精确控制延时时间,但需要额外的硬件支持。

二、中断问题:1. 中断产生的条件:中断是指在程序执行过程中,某个特定的条件满足时,CPU会暂停当前的工作,转入到一个中断服务程序中去执行。

中断产生的条件可以是外部触发比如按键、定时器、串口通信等,也可以是内部触发比如指令执行错误、电源电压不稳等。

2. 中断服务程序的编写:中断服务程序是在中断发生时被调用的程序,需要在程序中事先编写好。

一般情况下,中断服务程序需要尽量短小,以免影响正常的程序执行。

在中断服务程序中,需要首先保存CPU的现场,然后根据中断源的不同进行相应的处理,最后恢复CPU的现场,继续原来的程序。

3. 中断优先级:当多个中断同时发生时,需要按照一定的优先级来处理。

在单片机中,可以通过设置中断的优先级寄存器来实现优先级的分配。

4. 中断的使能与屏蔽:有些中断是可以被屏蔽的,有些是不能被屏蔽的。

可以通过设置中断使能寄存器和屏蔽寄存器来控制中断的开启和屏蔽。

总结:延时和中断问题是单片机编程中常见的问题,解决这些问题需要合理地选择延时方法和编写中断服务程序。

在实际的应用中,需要根据具体的要求和硬件配置来选择最适合的解决方案。

需要注意中断的优先级和使能与屏蔽,以确保程序的正常运行。

mcu时钟校准电路

mcu时钟校准电路

mcu时钟校准电路
MCU时钟校准电路是用于准确校准微控制器单元(MCU)内
部时钟的电路。

在MCU中,时钟是用于同步和控制内部操作
的重要信号。

时钟校准电路的基本原理是通过与外部精确时钟信号进行比较,来调整MCU内部时钟的频率和相位,以实现准确的时钟同步。

常见的时钟校准电路包括:
1. 校准自聚焦环(CFC):CFC电路通过反馈机制,根据外部参考时钟信号和内部时钟信号之间的相位差,调整内部时钟频率,以实现精确校准。

2. 相位锁定环(PLL):PLL电路通过调整内部振荡器的频率
和相位,将输出时钟信号锁定到外部参考时钟信号的频率和相位,从而实现时钟校准。

3. 精密外部时钟源:使用精密的外部时钟源(如GPS或原子钟)来提供准确的参考时钟信号,与MCU内部时钟进行比较
和校准。

时钟校准电路的设计需要考虑信噪比、灵敏度、稳定性等因素,以确保准确性和稳定性。

这对于许多需要高精度时钟的应用(如通信系统、计时器、数据采集等)至关重要。

MCU的时钟校准

MCU的时钟校准

校准时钟可以使用HP53132A仪表。

MCU的时钟校准在以下情况需进行MCU时钟的校准:1.在OMC发现每小时超出一个滑帧时。

2.当系统要求校准时。

(告警消息要求校准时)注意:MCU时钟的校准需由受过此方面培训的工程师操作。

gclk_cal_mode命令只能在BTS中使用。

进行MCU时钟的校准时要在没有呼叫发生时进行。

在上电后OCXO要有30分钟的预热时间,以使其达到正常工作温度。

仪器:1。

一台IBM兼容的PC机。

2.9转9的串口线。

3.铯或铷时钟源(1M到10M输出)。

4.能使用外部时钟源的频率计,例如:HP5385A或其它同功能设备。

准备工作:按以下步骤进行准备工作:1.用9转9串口线连接PC与MCU的TTY。

2.在PC上启动终端仿真程序。

3.将10M频率发生仪输出作为频率计的外部参考时钟源。

4.设置频率计的frequency gate time为10秒,显示数值的有效位为10位。

5.用测试线将MCU的时钟输出信号接至频率计的输入口。

MCU时钟输出口:第一针:地第三针:8KHZ输出。

步骤:1。

在MMI_RAM 1015提示符下键入以下命令:gclk_cal_mode此命令通知MCU的软件和同步功能将要进行时钟校准。

(在备用MCU处于激活状态时,此命令对主用MCU无效)此命令执行后将出现以下提示及确认信息:Site <local site number> starting GCLK CALIBRATION MODE. If this is a single MCU site, the site will be down until calibration is complete.Are you sure (y=yes, n=no)? Y如输入‘y’以外的键,此命令将无效。

如输入‘y’,MCU将进入频率校准模式。

2.系统将出现以下提示:Frequency Counter Connected, Enter y when ready, or a to abort test y如输入‘y’以外的键,此命令将无效,MCU将进入退出频率校准模式。

单片机编程技巧--功能强大的时钟中断

单片机编程技巧--功能强大的时钟中断

单片机编程技巧--功能强大的时钟中断功能强大的时钟中断在单片机程序设计中,设置一个好的时钟中断,将能使一个CPU发挥两个CPU的功效,大大方便和简化程序的编制,提高系统的效率与可操作性。

我们可以把一些例行的及需要定时执行的程序放在时钟中断中,还可以利用时钟中断协助主程序完成定时、延时等操作。

下面以6MHz时钟的AT89C51系统为例,说明时钟中断的应用。

定时器初值与中断周期时钟中断无需过于频繁,一般取20ms(50Hz)即可。

如需要百分之一秒的时基信号,可取10mS(100Hz)。

这里取20mS,用定时器T0工作于16位定时器方式(方式1)。

T0的工作方式为:每过一个机器周期自动加1,当计满0FFFFh,要溢出时,便会产生中断,并由硬件设置相应的标志位供软件查询。

即中断时比启动时经过了N+1个机器周期。

所以,我们只要在T0中预先存入桓霰嚷 ?FFFFh小N的数,然后启动定时器,便会在N个机器周期后产生中断。

这个值便是所谓的“初值”。

下面计算我们需要的初值:时钟为6MHz,12个时钟周期为一个机器周期,20mS中有10000个机器周期。

(10000)10=(2710)16,则0FFFFh-2710h+1=0D8F0h。

由于响应中断、保护现场及重装初值还需要7~8个机器周期,把这个值再加上7,即T0应装入的初值是0D8F7h。

每次中断进入后,先把A及PSW的值压入堆栈,然后即把0D8F7h装入T0。

设置一个单元,每次中断加1我们可以取内部RAM中一个单元,取名为INCPI(Increase Per Interrupt),在中断中,装完T0初值后,用INC INCPI指令将其加一。

从这个单元中,无论中断程序还是主程序,都可以从中获得20mS的1~256之间任意整数倍的信号。

例如:有一段向数码管送显的程序,需要每0.5秒执行一次以便刷新显示器,便可以设一单元(称为等待单元)W_DISP,用/MOV A,INCPI/ADD A,#25/MOV W_DISP,A/语句让其比当前的INCPI值大25,然后在每次中断中检查是否于INCPI值相等。

定时器写延时1ms函数

定时器写延时1ms函数

定时器写延时1ms函数在嵌入式系统中,经常需要进行时间控制。

定时器是一种硬件设备,它可以生成一个周期性的中断信号,我们可以利用这个中断信号来实现定时器功能。

在嵌入式系统中,经常需要进行短时间的延时操作。

为了方便使用,我们可以将常用的延时操作封装成函数。

本篇文章将介绍如何利用定时器编写一个延时1ms的函数。

1. 硬件选型在笔者的开发环境中,采用了STM32F103系列微控制器,选用了其内部的TIM2定时器。

TIM2定时器是一个16位的定时器,它可以配置为不同的工作模式,比如定时器模式、输入捕获模式、PWM输出模式等等。

对于我们要编写的延时函数,采用定时器模式就可以实现。

2. 配置定时器工作模式在使用定时器之前,需要进行一些初始化配置。

我们要配置TIM2定时器为定时器模式,采用内部时钟源这种工作模式,周期为1ms。

初始化代码如下所示:```void Delay_Init(void){// 使能定时器时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);// 定时器配置TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_Prescaler = 7200 - 1; // 分频系数=7200,即1us为一个计数单位TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式TIM_TimeBaseInitStruct.TIM_Period = 1000; // 计数周期=1msTIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);// 开始计时TIM_Cmd(TIM2, ENABLE);}```上述代码中,我们首先使能TIM2的时钟,并配置了定时器的工作模式。

DSP 课件1ms周期中断

DSP 课件1ms周期中断

第7章事件管理器模块(EV)7.2.7 通用定时器的中断实现源程序代码:(1)所需的复位和中断向量定义文件“vectors.asm”.ref _nothing;直接返回的中断服务程序符号.ref _c_int0 ;复位向量符号.sect ".vectors"RSVECT B _c_int0 ;PM 0复位向量 1INT1 B _nothing ;PM 2 中断优先级1 4INT2 B _T1INT ;PM 4 中断优先级2 5INT3 B _nothing ;PM 6 中断优先级3 6INT4 B _nothing ;PM 8 中断优先级4 7INT5 B _nothing ;PM A 中断优先级5 8INT6 B _nothing ;PM C 中断优先级6 9(2)主程序// 该程序利用了定时器1的周期中断功能,每1ms产生一次中断#include "register.h"// 屏蔽中断程序void inline disable(){asm(" setc INTM");}// 开总中断程序void inline enable(){asm(" clrc INTM");}// 系统初始化子程序initial(){asm(" setc SXM");// 符号位扩展有效asm(" clrc OVM");// 累加器中结果正常溢出asm(" clrc CNF");// B0被配置为数据存储空间*SCSR1=0x81FE;// CLKIN=6M,CLKOUT=4*CLKIN=24M*WDCR=0x0E8;// 不使能看门狗,因为SCSR2中的WDOVERRIDE// 即WD保护位复位后的缺省值为1,故可以用// 软件禁止看门狗*IMR=0x0002;// 允许INT2中断*IFR=0x0FFFF;// 清除全部中断标志,"写1清0"WSGR=0X00;// 禁止所有的等待状态}// 定时器1的初始化子程序125int timer1int(){*EVAIMRA=*EVAIMRA|0X0080;// 允许定时器1的周期中断*EVAIFRA=*EVAIFRA&0X0080;// 清除定时器1周期中断标志*T1CON=0X160C;// Timer1为连续增计数模式,预分频值为64,使用内部时钟*T1PER=0X0177;// Timer1的周期寄存器的值根据1ms延时和预分频值确定*T1CNT=0X00;// Timer1的计数器清零}// 定时器1周期中断服务程序void interrupt T1INT(){int flag;// 定义一个局部变量flag=*EVAIFRA&0X0080;if(flag!=0x0080){enable( );// 允许总中断return;// 如果不是定时器1周期中断,则直接返回}// 如果是定时器1周期中断定时器1的周期中断,则执行下面的程序*T1CNT=0X00;// 定时器1的计数器重新赋0*EVAIFRA=*EVAIFRA&0X0080;// 清除定时器1周期中断标志,否则以后的中断将被忽略enable( );// 允许总中断,因一进中断服务程序后总中断就自动关闭了return;// 中断返回}// 其它优先级的中断服务程序,虽然程序中已经禁止,// 但可能由于干扰会引起他们的执行,故该中断服务程序无额外操作,直接返回void interrupt nothing(){enable( );// 允许总中断,因一进中断服务程序后总中断就自动关闭了return;// 中断返回}// 主程序main(){disable();// 初始化时禁止中断initial();// 系统初始化timer1int();// 定时器1的初始化enable();// 允许总中断*T1CON=*T1CON|0X0040;// 启动Timer1while(1){;// 等待中断发生}}126。

定时器写延时1ms函数

定时器写延时1ms函数

定时器写延时1ms函数在嵌入式系统中,经常需要实现延时函数,用于等待一定的时间后再执行下一步操作。

比如,控制舵机、控制LED闪烁等等。

本文将介绍如何使用定时器来实现一个延时1ms的函数。

首先,我们需要了解定时器的原理。

定时器是一种计时设备,它可以周期性地产生中断信号。

比如,我们可以将定时器的计数值设置为1000,当计数值达到1000时,定时器会产生一次中断信号。

我们可以利用这个中断信号来实现延时操作。

在MCU中,通常会有多个定时器可供使用。

我们可以根据需要选择一个合适的定时器,并设置它的计数值和预分频器的值。

预分频器用于将定时器的时钟源分频,以便得到一个更低的计数速率。

比如,如果我们需要1ms的计时周期,而定时器的时钟源频率为1MHz,那么我们可以设置预分频器为1000,计数值为1000,这样定时器就可以每隔1ms产生一次中断信号。

下面是一个使用STM32F103C8T6芯片的例子代码:```c#include 'stm32f10x.h'void delay_ms(uint32_t ms){RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能TIM2时钟TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Period = ms - 1; // 设置计数值 TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 设置预分频器TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);TIM_Cmd(TIM2, ENABLE); // 启动定时器while (TIM_GetFlagStatus(TIM2, TIM_FLAG_Update) == RESET); // 等待中断信号TIM_Cmd(TIM2, DISABLE); // 停止定时器TIM_ClearFlag(TIM2, TIM_FLAG_Update); // 清除中断标志}int main(){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // 使能GPIOC时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; // PC13对应的LEDGPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 最大输出速率50MHzGPIO_Init(GPIOC, &GPIO_InitStructure);while (1){GPIO_SetBits(GPIOC, GPIO_Pin_13); // 点亮LEDdelay_ms(500); // 延时500msGPIO_ResetBits(GPIOC, GPIO_Pin_13); // 熄灭LEDdelay_ms(500); // 延时500ms}}```在上面的代码中,我们定义了一个delay_ms函数用来实现延时操作。

单片机的延时与中断问题及解决方法

单片机的延时与中断问题及解决方法

单片机的延时与中断问题及解决方法随着单片机应用的广泛,它的延时和中断问题成为了开发者关注的焦点。

本文将针对这两个问题进行探讨,并给出相应的解决方法。

在单片机的应用中,经常需要一定的延时。

延时有两种实现方式:1. 软件延时:利用单片机的定时器或者计数器实现。

通过设定定时器的初值和工作模式,可以得到精确的延时时间。

我们希望延时1秒钟,可以设置一个1000ms的定时器,然后进入循环判断定时器是否达到设定值,达到则退出循环。

2. 硬件延时:利用外部硬件电路实现延时。

这种方式的延时精度较高,但是需要额外的硬件电路支持,相对复杂一些。

针对延时问题,我们可以采取以下解决方法:1. 选择合适的延时方式:软件延时和硬件延时各有优劣,开发者可以根据具体应用场景选择合适的延时方式。

2. 调试延时程序:在开发过程中,可以通过在延时程序中加入调试信息,如打印当前延时时间等,来判断是否存在延时问题,以及确定问题所在。

可以通过改变定时器的工作模式、调整定时器的初值等参数,来优化延时效果。

3. 使用延时函数库:延时操作是单片机开发中很常见的操作,有很多延时函数库可供使用。

这些函数库通常经过测试和优化,可以提供较为稳定和准确的延时效果。

中断是单片机开发中常用的一种机制,可以及时响应外部输入或内部事件。

在使用中断时也会遇到一些问题:1. 中断优先级:当多个中断同时发生时,需要设置不同中断的优先级,以确保先处理较为重要的中断。

可通过配置中断相关寄存器来设置中断优先级,其中有些单片机可以实现硬件自动判断和调整中断优先级。

2. 中断嵌套:有些情况下,中断可能会在其他中断的中间发生。

这种情况下,需要对中断进行嵌套处理。

嵌套中断的实现方法和优先级设置有关,可以使用优先级判断和保存/恢复中断状态等方法来处理嵌套中断。

3. 中断处理时间过长:如果中断处理时间过长,会导致其他中断被延迟或错过。

在编写中断服务函数时,应尽量减少代码量和运行时间,避免出现延迟问题。

单片机的延时与中断问题及解决方法

单片机的延时与中断问题及解决方法

单片机的延时与中断问题及解决方法单片机的延时和中断是在程序设计中经常遇到的两个问题。

延时是指在程序中需要暂停一段时间,而中断是指在程序执行中出现某个特定的事件需要处理。

一、延时的问题及解决方法:延时在单片机编程中经常用到,常用的延时方法有软件延时和硬件延时两种。

1. 软件延时:软件延时是通过循环来实现的。

通过编写一个循环,在循环中一直执行一些无关紧要的操作,以此来延时一段时间。

我们可以编写一个延时函数delay_us(),通过控制循环执行的次数来实现微秒级的延时。

具体实现如下:```void delay_us(unsigned int time){unsigned int i;for(i=0;i<time;i++);}```这种延时的精度是由单片机的主频决定的,频率越高,延时越精确,但是也会消耗更多的单片机资源。

2. 硬件延时:硬件延时是通过单片机的定时器来实现的。

定时器可以根据需要设置一个定时值,当达到定时值时,会产生一个中断,我们可以在中断服务函数中进行延时的处理。

我们可以编写一个延时函数delay_ms(),通过设置定时器的初值和中断服务函数来实现毫秒级的延时。

具体实现如下:```void delay_ms(unsigned int time){TMOD |= 0x01; // 设置定时器0为模式1TH0 = (65536 - time*1000/1.0857)/256; // 设置定时器的初值TL0 = (65536 - time*1000/1.0857)%256;TR0 = 1; // 启动定时器0while(!TF0); // 等待定时器0溢出TR0 = 0; // 关闭定时器0TF0 = 0; // 清除溢出标志}```这种延时的精度更高,而且不会消耗太多的单片机资源,但是需要更多的编程操作。

二、中断的问题及解决方法:中断在单片机编程中非常重要,可以及时地处理某些特定的事件,提高程序的效率。

STM32Cubemx配置定时器定时1mS

STM32Cubemx配置定时器定时1mS

STM32Cubemx配置定时器定时1mS 最近才发现原来我把定时器⾥的配置参数代表的意义给搞混了,这⾥记录⼀下,防⽌以后⾃⼰忘记。

以建⽴⼀个定时1mS定时器为例: 1、先打开定时器 2、配置好时钟 3、配置定时器设置 重点来了,以前在这⾥我⼀直以为这⾥配置的就是时间,然后在调频率的时候,⼀直不对劲,知道查阅了硬⽯的资料才发现,这⾥配置的是进⼊定时器中断的频率,然后要定的时间要跟据这个频率来定时的。

由这个图可见,这⾥配置的是定时器产⽣中断的频率,然后再跟据频率与时间的关系推出定时的时间。

所以定时器频率为 f = 72M / Prescaler / Period = 72000 000 / 72 /1000 = 1000Hz; 定时时间T = 1 / f 则: 1s / 1000Hz = 1000 000us / 1000Hz = 1000us =1ms。

这样就可以定时1ms了啦,如果要做PWM频率调频,就直接改 pre 与 per 算出 f 就可以了。

具体公式如下图(上⾯的计算我是为了⽅便理解把公式逆运算了⼀次): 最后使⽤定时器中断跟关闭定时器中断以及回调函数即可, 使⽤中断的时候注意要先开启中断HAL_TIM_Base_Start_IT(&htim1); //使⽤定时器的时候调⽤这个函数启动HAL_TIM_Base_Stop_IT(&htim1); //停⽌定时器的时候调⽤这个函数关闭void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(htim->Instance == TIM1) { //编写回调逻辑,即定时器1定时1MS后的逻辑 }}补充:最后记得⽣成STM32Cubemx⽂件时打开定时器中断,不然进不了回调函数,⼀般的话习惯⽤TIM3做定时器。

STM32库开发实战指南-M4:18-SysTick-系统定时器

STM32库开发实战指南-M4:18-SysTick-系统定时器

10
* SystemFrequency / 1000000 1us 中断一次
11
*/
12
if (SysTick_Config(SystemCoreClock / 100000)) {
13
/* Capture error */
14
while (1);
15
}
16 }
SysTick 初始化函数由用户编写,里面调用了 SysTick_Config()这个固件库函数,通过
SysTick 属于单片机内部的外设,不需要额外的硬件电路来自剩下的只需一个 LED 灯即 可。
18.3.2 软件设计
这里只讲解核心的部分代码,有些变量的设置,头文件的包含等并没有涉及到,完整 的代码请参考本章配套的工程。我们创建了两个文件:bsp_SysTick.c 和 bsp_ SysTick.h 文 件用来存放 SysTick 驱动程序及相关宏定义,中断服务函数放在 stm32f4xx_it.h 文件中。
16
17
// 设置系统定时器的时钟源为 AHBCLK=180M
18
// 使能系统定时器中断
19
// 使能定时器
20
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
21
SysTick_CTRL_TICKINT_Msk |
22
SysTick_CTRL_ENABLE_Msk;
零死角玩转 STM32—F429
零,同时还会清除在 SysTick 控制及状态寄 存器中的 COUNTFLAG 标志
表 18- 5 SysTick 校准数值寄存器
位段 名称
类型 复位值 描述

STM32MCU串口使用编程步骤

STM32MCU串口使用编程步骤

STM32MCU串口使用编程步骤2023-5-10CamusLu串行口是MCU开发过程中的常用部件,下面是使用USART1时编程的步骤;1、首先要配置系统时钟和使能外设时钟:void RCC_Configuration(void){SystemInit();RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);}2、然后需要在I/O口配置函数GPIO_Configuration()中对USART1设置void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;//USART1_TX GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9//USART1_RX GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10}3、要在串口初始化函数USART_Config()中添加如下程序:void USART_Config(USART_TypeDef* USARTx,uint32_t BaudRate){USART_ART_BaudRate = BaudRate;//速率9600bpsUSART_ART_WordLength = USART_WordLength_8b;//数据位8位USART_ART_StopBits = USART_StopBits_1;//停止位1位USART_ART_Parity = USART_Parity_No;//无校验位USART_ART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控USART_ART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式/* Configure USART1 */USART_Init(USARTx, &USART_InitStructure);//将配置好的参数设置到串口USARTx中去/* Enable USART1 Receive and Transmit interrupts */USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE); //使能接收中断USART_ITConfig(USARTx, USART_IT_TXE, ENABLE);//使能发送缓冲空中断/* Enable the USART1 */USART_Cmd(USARTx, ENABLE);}4、在中断源配置函数中设值串口1中断的优先级void NVIC_Configuration(void){NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;设置串口1中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//子优先级为0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能NVIC_Init(&NVIC_InitStructure);}5、设计发送固定长度数据包函数void USART_OUTCOMMAND(USART_TypeDef* USARTx, uint8_t *Data,unsigned char length){char i=0;USART_GetFlagStatus(USARTx, USART_FLAG_TC);//为了使得第一个字符能被成功发送while(i<length){USART_SendData(USARTx, Data[i]);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);i++;}}6、再添加USART1的中断服务程序该中断程序是串口接收与发送中断的共用接口程序,如果串口的发送不使用中断最好将串口初始化程序中的USART_ITConfig(USARTx, USART_IT_TXE, ENABLE);//使能发送缓冲空中断这条指令去掉,这样串口发送就不会进入中断,如果这一条没有去掉,服务程序中if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //禁止发送缓冲器空中断,这两条指令必不可少,不然这条程序一直会处于串口发送标志位被使能状态。

MCU的基础--时钟系统学习教程

MCU的基础--时钟系统学习教程

MCU的基础--时钟系统学习教程
时钟系统是一颗MCU的基础,MCU的一个重要考核指标。

PIC32MZ EF系列采用MIPS32 M级核,工作频率可以达到200MHz。

时钟系统也比较复杂,配置的寄存器比较多,下面就对照Harmony里面的时钟配置进行简单的介绍。

PIC32MZEF振荡器系统具有以下模块和特性:
共有5个外部和内部振荡器可选作时钟源
具有用户可选的输入分频器、倍频器和输出分频器的片上PLL,可提升特定内部和外部振荡器源的工作频率
特定振荡器源具有片上用户可选的后分频器
可采用软件控制在各个时钟源之间切换
检测时钟故障和允许通过专用备份FRC(Back-up FRC,BFRC)安全恢复或关闭应用的故障保护时钟监视器(Fail-Safe Clock Monitor,FSCM)
供USB外设专用的片上PLL
灵活的参考时钟输出
外设的多个时钟分支可使其获得更好的性能灵活性
采用输出分频器实现时钟切换/摆动控制
看看手册上的时钟树,仔细看看就可以对时钟系统有一个大体的了解,具体参数的设置就要仔细研究寄存器的含义了。

时钟方面的寄存器列表,寄存器很多
Harmony里面的时钟配置很人性化,和手册上的图表是一样的形式,这样就很方便了,这里直接进行简单的参数选择就可以了,下面就大概介绍下时钟系统的配置
1,MCU有5个时钟源,外部高频主振荡器,外部低频振荡器,内部快速RC,内部备用。

单片机的延时与中断问题及解决方法

单片机的延时与中断问题及解决方法

单片机的延时与中断问题及解决方法单片机作为嵌入式系统的核心部件,具有很强的实时性和稳定性要求。

在单片机的编程过程中,延时和中断是两个非常重要的概念。

延时是指在程序执行过程中,需要等待一定的时间才能继续执行下一条指令。

延时的作用在于控制程序的执行顺序,实现各种功能的时间控制和同步。

中断是指在程序执行过程中,当发生某些特定的事件时,硬件或者软件可以临时中断当前的执行流程,转而执行另一个特定的程序段,待中断处理完成后再返回到原来的程序流程中。

中断的作用在于及时响应各种外部事件,提高程序的实时性和效率。

延时和中断在单片机编程中经常会遇到各种问题,下面将针对延时和中断问题进行分析,并提出解决方法。

1. 延时时间不准确延时时间不准确的原因可能有多种,例如单片机的工作频率不稳定、指令执行时间不固定、编译器优化等。

为了解决延时时间不准确的问题,可以采用以下几种方法:(1)使用定时器定时器是单片机中非常重要的一个外设,可以产生精确的延时。

通过配置定时器的初值和工作模式,可以实现精确的延时功能。

(2)使用外部时钟源单片机的内部时钟源可能存在波动和不稳定的情况,可以通过外部时钟源来提供稳定的工作频率,从而提高延时的准确性。

(3)校准延时时间通过实际测试和校准,可以得到准确的延时时间,并在程序中使用这个准确的延时时间。

2. 延时过长导致程序响应慢在一些需要实时响应的程序中,如果延时过长会导致程序响应慢,对系统性能造成影响。

为了解决延时过长导致程序响应慢的问题,可以采用以下几种方法:通过定时器中断来实现延时,可以避免长时间的忙等待,提高程序的实时响应性。

(2)使用多任务机制采用多任务机制,将需要长时间延时的任务放到后台运行,以提高系统的响应能力。

(3)优化算法对需要延时的任务进行算法上的优化,尽量减少延时的时间,提高系统的实时性。

1. 中断响应不及时中断响应不及时的原因可能是中断服务程序执行时间过长,导致无法及时响应其他的中断请求。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

******************************************************************************* 学习内容:
1:Realtek的时钟
2:1ms 中断实现
3:volatile word time
20111027
******************************************************************************* 1:Realtek的时钟
如果把Scaler比作是一个系统的大脑,它控制着系统的各种动作行为;那么,时钟则可以比喻成是这个系统的心脏,它控制的是整个系统要以什么状态来工作,是兴奋亦或是休闲/睡眠。

时钟周期与机器周期的关系
时钟周期:指系统时钟频率,可以是直接来自外部XTAL,也可以是来自其它时钟来源,如PLL。

机器周期:指程序运行一个基本指令操作需要的时间,8051单片机需要12个时钟周期,AVR单片机只需要1个时钟周期,还有些单片的机器周期为6个时钟周期或者4个时钟周期。

Realtek的时钟周期来源可以有三个:
1:外部XTAL
2:内部时钟(Lower Power IC上才有)
3:外部XTAL经过M2PLL倍频分频后的时钟,在软体中的参数设定为:_EMCU_XTAL ,它的单位为K
以Lenovo Li2361机种为例:当XTAL使用的是27M Hz,实际系统正常跑的时钟为经过PLL倍频后的时钟:_EMCU_XTAL=33.5M Hz。

在DC OFF 或Powersaving时,时钟是以外部XTAL=27M Hz来跑。

具体设定看CMcuSelectFlashClk(bit select)这个函数:
由上可知,在正常模式下,系统使用频率比在powersaving或DC OFF时使用的时钟频率要高,相应系统的功耗会比较大。

因Lenovo_Li2361使用的这颗IC RTD2743PD并非LOW POWER 的IC,所以,它在POWER SAVING时,并未以一个更低的内部时钟来进行工作。

Realtek的嵌入式51内核的机器周期,可以是12个时钟周期,也可以是4个时钟周期,具体是以哪个机器来跑,可以参考寄存器:CKCON --8Eh,
当它设定为0x00时,表示当前的机器周期是以12个时钟周期来跑;
当它设定为0x01时,表示当前的机器周期是以4个时钟周期来跑。

在MCU初始化时,CKCON被初始化为0x00,表示系统的机器周期为12个时钟周期。

整个系统是使用哪一颗心脏在运行,就决定了这个系统在做某些行为的快与慢。

附件是之前在BenQ 机种上发生的一个BUG的视频文件,从中,我们可以看到,平常画OSD的速度是很快的,因为平常的情况下,整个系统的时钟心脏是在一个比较快的频率。

当某种条件下,系统的时钟心脏发生的突变,变成了以一个很慢的频率在动作时,连画一个OSD所需要的时候都变得很长,OSD可以认为是一点一点在慢慢的画出来。

(这个BUG 目前依然无解,因为无法找到它是满足什么条件下进去了那么慢的时钟心脏,当然,会出现这么慢的情况还有另外一个可能,就是系统不断的执行中断,导致正常画OSD的动作被无限次中断给打断,导致速度变慢,我个人是倾向于是进入一个错误的时钟在跑整个系统。


2:1ms 中断实现
软体中有设计一个功能:每隔1ms执行中断一次,用来作为系统的一些时间事件的计数使用,比如开机LOGO要2s后关闭,nosignal的OSD要6s后关闭等等。

1ms一中断的功能,Realtek的CODE是使用8051内部资源中的Timer0来实现的。

在AC一上电的时候,做CMcuInitial()时,把TMOD设定成0x11.
TMOD(定时器/计数器方式控制寄存器)介绍:
GATE:当GATE设定为0时,计时器/计数器是否能工作,取决于寄存器TRx是否为1,初始化时,TRx=0,计时器/计数器不工作,在程序往下执行时,TRx会被置成1,此时,计时器/计数器才能真正的开始工作。

C/T:选择它是作为计时器还是计数器来使用?
C/T=0:当前作为计时器使用
C/T=1:当前作为计数器使用
M1/M0:设定计时器/计数器的计数模式:
0/0: 13位定时/计数方式,最多能计到2的13次方,也就是8192次
0/1:16位定时/计数方式,最多能计到2的16次方,也就是65536次
1/0,1/1 :都是8位定时/计数方式,最多能计到2的8次方,也就是256次
由上可知,Realtek的程序中,把TMOD=0x11,让Timer0/ Timer1都工作在计时方式,且都是设定为16位的计时器。

计时器中断介绍:
计时器中断可以用以下图形来形象的描述:
计时器可以比喻成一个水桶,当以每个系统时钟的速度往水桶里进水,在不做任何设定处理的情况下,要把一个16位计时器的水桶装满水,需要65536个时钟周期。

当我们需要一个比较快的速度就让它装满水,只需要往桶里预先装一些水,再以这个系统时钟的速度往桶里装水,就可以实现在我们要求的时间内就产生一个溢出中断。

Lenovo Li2361机种使用的是一颗27M的XTAL,而正常工作的时候,系统时钟
_EMCU_XTAL=33.5M Hz。

正常工作时,计时器0的预丢值如下:
_TIMER0_COUNT_HBYTE = 0xF5
_TIMER0_COUNT_LBYTE = 0x39
由计时器0,工作在16位计时器模式下,预丢值为:0Xf539,这时,产生1ms溢出中断的时间计算公式如下:
其中:
t:表示溢出时间
M:表示系统机器周期,Lenovo Li2361的软体设定系统周期为12
F:表示系统时钟,Lenovo Li2361的软体设定下,正常工作时钟周期为33.5MHZ,DC OFF / PowerSaving下时钟周期为27MHZ
n:表示当前计时器工作模式是多少位的计时器,软体中设定为16位。

X:表示计时器的预丢值,正常工作时的预丢值为0XF539=62777
把以上参数带到公式:
DC OFF / PowerSaving时,计时器0的预丢值如下:
_TIMER0_COUNT_EXXTAL_HBYTE = 0xF7
_TIMER0_COUNT_EXXTAL_LBYTE = 0x36
预丢值为:0xF736=63286
时钟周期为27MHZ
3:volatile word time
在CTimerEventTable参数中,把Time这个WORD变量定义为volatile,为什么呢?
在CTimerHandler(void)这个函数(非中断函数),可以看到,对Time是否等于0进行了连续的两次判定。

在keil C编译软体中,点help选项,搜索volatile,可得以下信息:
像这种对同一个参数连续进行两次判定的,编译器会自动优化,实际只会执行第一次的参数判定,第二次判断时,编译器不会对它进行重载动作,就算此时我们的参数变量的数值已经有变化。

在对参数进行volatile的强制定义后,告诉编译器,这个参数不需要优化处理,在编译到判定的位置时,编译器会老老实实地严格按两次判定。

为什么要对Time这个参数连续进行两次判定是否已为0??
Realtek的Time参数的判定是否为0动作,是放在非中断的函数里面执行(Mstar的程序中,对time的判定动作是直接放到中断函数里执行),这样做的目的是让中断函数执行的语句尽可能的少,时间才会更精准。

Time的变量类型,定义为Word类型,两个byte,我们的51单片机又是8bit的,去判定两byte的值是否已为0,需要对这个word类型变量load两次。

软体中,又有定义一个
1ms执行一次中断的动作,此时,有一定的概率会在Time=0x0100的时候会被误判成0x0000,具体图示如下:。

相关文档
最新文档