Atmega16-定时器1的使用 step by step。
之前完成了定时器2的各项功能的测试后,这里就很容易做了。
编译环境:AVR Studio 4.19 +avr-toolchain-installer-3.4.1.1195-win32.win32.x86
芯片型号:ATmega16
芯片主频:8MHz
测试说明:
1、 OC1A和 OC1B引脚输出比较匹配的波形
2、 PA2在 TOV1中断时取反
3、 PA3在 OCF1A中断时取反
4、 PA5在 OCF1B中断时取反
5、 PA6在 ICF1中断时取反
------------------------------------------------------------------------------------------------------------------------------------
小结:
1、最好使用 CTC模式来做定时功能。
因为这样就只需要设置OCR1A,不需要每次TOV1中断都要重新设置TCNT1的计数初值。
2、CTC模式下、OC1A和OC1B的频率由OCR1A或ICR1决定,OCR1A和OCR1B都用来控制OC1A和OC1B的相位。
CTC模式下的脉冲频率最大可达4MHz。
3、快速/高频PWM用于:功率调节、整流、ADC
当OCR1A/OCR1B超过TOP值时,依然有PWM波形输出:TCNT1=(OCR1A或OCR1B)&TOP时发生比较匹配
可以得到相当精确的PWM频率和占空比,如38KHz、1/3占空比的红外载波
可以用OC1A引脚输出类似CTC模式的方波
4、相位修正对称用于:电机控制
修改TOP值可能导致上升斜坡和下降斜坡长度不一致,导致一个周期的波形不对称。
结果就是占空比超出预期或低于预期。
如果这有影响,就应该使用相位与频率修正PWM来做TOP值/频率可变的PWM。
5、相频修正PWM,其作用与意义有待理解。
6、对于ICF1中断,还有异常,见question-001。
-------------------------------------------------------------------------------------------------------------------------------------
第一步: 普通模式
说明:
1、使用定时器1的作为定时器使用,每次溢出后PA2的电平取反,由此可得知溢出时间。
测试代码:
Drv_Timer.h
typedef enum
{
INT_MODE_TOV = 0,
INT_MODE_OCF = 1,
INT_MODE_ICF = 2,
INT_MODE_OCF1A = 3,
INT_MODE_OCF1B = 4
} TIMER_INT_MODE;
typedef enum
{
T1_COM_MODE_NONE = 0,
T1_COM_MODE_TOGGLE = 1,
T1_COM_MODE_CLEAR = 2,
T1_COM_MODE_SET = 3,
T1_WGM_NOMAL = 0,
T1_WGM_8_PHASE_PWM = 1,
T1_WGM_9_PHASE_PWM = 2,
T1_WGM_10_PHASE_PWM = 3,
T1_WGM_CTC = 4,
T1_WGM_8_FAST_PWM = 5,
T1_WGM_9_FAST_PWM = 6,
T1_WGM_10_FAST_PWM = 7,
T1_WGM_PHASE_FRQ_PWM_ICR1 = 8,
T1_WGM_PHASE_FRQ_PWM_OCR1A = 9,
T1_WGM_PHASE_PWM_ICR1 = 10,
T1_WGM_PHASE_PWM_OCR1A = 11,
T1_WGM_CTC_ICR1 = 12,
T1_WGM_SERVED = 13,
T1_WGM_FAST_PWM_ICR1 = 14,
T1_WGM_FAST_PWM_OCR1A = 15,
T1_CLK_SOURCE_NONE = 0,
T1_CLK_SOURCE_CLK_1 = 1,
T1_CLK_SOURCE_CLK_8 = 2,
T1_CLK_SOURCE_CLK_64 = 3,
T1_CLK_SOURCE_CLK_256 = 4,
T1_CLK_SOURCE_CLK_1024 = 5,
T1_CLK_SOURCE_T1_FALL = 6,
T1_CLK_SOURCE_T1_RAISE = 7
} TIMER1_MODE;
typedef enum
{
T1_ICP_FALL_EDGE = 0,
T1_ICP_RAISE_EDGE = 1
} TIMER1_ICP;
Drv_Timer.c
// ==========================================================================================================
// 定时器1初始化
//
// 参数:OCM1A_mode 通道A比较匹配/PWM输出模式选择
// OCM1B_mode 通道B比较匹配/PWM输出模式选择
// com_mode 工作模式/波形产生模式选择
// clk_source 时钟源和预分频选择
//
// PWM模式下、写TCCR1A时需要清除FOC1A/B
// 写TCCR1B时需要清除bit5
//
// ==========================================================================================================
void Drv_Timer1_init(const uint8_t com_mode, const uint8_t OCM1A_mode, const uint8_t OCM1B_mode, const uint8_t clk_source)
{
TCCR1A = ((OCM1A_mode & 0x03) << 6) | // 通道A比较匹配/PWM输出模式选择
((OCM1B_mode & 0x03) << 4) | // 通道B比较匹配/PWM输出模式选择
((com_mode & 0x03) << 0); // 工作模式/波形产生模式选择(WGM[11:10])
TCCR1B = (((com_mode & 0x0C) >> 2) << 3) | // 工作模式/波形产生模式选择(WGM[13:12])
( (clk_source & 0x07) << 0); // 时钟源和预分频选择
}
// ==========================================================================================================
// TIMER1 中断使能
//
// 参数:mode = INT_MODE_TOV 或 INT_MODE_ICF 或 INT_MODE_OCF1A 或 INT_MODE_OCF1B
// enable = ENABLE 或 DISABLE
//
// 可以单独使能/禁止一种模式的中断
//
// ==========================================================================================================
void Drv_Timer1_INT_Enable(const uint8_t mode, const uint8_t enable)
{
if(INT_MODE_TOV == mode)
{
if(DISABLE == enable)
{
TIMSK &= ~(1 << TOIE1);
}
else
{
TIMSK |= (1 << TOIE1);
}
TIFR |= (1 << TOV1);
return ;
}
if(INT_MODE_OCF1A == mode)
{
if(DISABLE == enable)
{
TIMSK &= ~(1 << OCIE1A);
}
else
{
TIMSK |= (1 << OCIE1A);
}
TIFR |= (1 << OCF1A);
return ;
}
if(INT_MODE_OCF1B == mode)
{
if(DISABLE == enable)
{
TIMSK &= ~(1 << OCIE1B);
}
else
{
TIMSK |= (1 << OCIE1B);
}
TIFR |= (1 << OCF1B);
return ;
}
if(INT_MODE_ICF == mode)
{
if(DISABLE == enable)
{
TIMSK &= ~(1 << TICIE1);
}
else
{
TIMSK |= (1 << TICIE1);
}
TIFR |= (1 << ICF1);
}
}
// ==========================================================================================================
// TIMER1 溢出中断服务程序
//
// ==========================================================================================================
ISR(TIMER1_OVF_vect)
{
PORTA ^= (1 << PA2);
}
main.c
// ==========================================================================================================
// 主函数
// ==========================================================================================================
#include #include #include "watch_dog.h" #include "Drv_Timer.h" #include "_noinit.h" #include "system.h" #include "sys_timer.h" #include "config.h" // ========================================================================================================== // 伪中断BADISR_vect // // ========================================================================================================== ISR(BADISR_vect) { } // ========================================================================================================== // main函数 // ========================================================================================================== int main(void) { // --------- // 关全局中断 cli(); // 系统初始化 sys_init(); // PA[5:2]初始化为输出0 DDRA = (1 << DDA2) | (1 << DDA3) | (1 << DDA5) | (1 << DDA6); PORTA &= ~((1 << PA2 ) | (1 << PA3 ) | (1 << PA5 ) | (1 << PA6 )); // 定时器1 初始化:普通模式、COM1A不启用、COM1B不启用、8预分频 Drv_Timer1_init(T1_WGM_NOMAL, T1_COM_MODE_NONE, T1_COM_MODE_NONE, T1_CLK_SOURCE_CLK_8); // 使能TOV1中断 Drv_Timer1_INT_Enable(INT_MODE_TOV, ENABLE); // 开全局中断 sei(); // --------- while(1) { } return 0; } 测试结果: 1、 PA2引脚电平每个 66ms翻转一次。 定时器1溢出周期为 T = ((1.0/8000000)*1000000) * 8 * 65536 / 1000 = 65.536 ms。 两者基本一致。 ------------------------------------------------------------------------------------------------------------------------------------- 第二步: CTC模式 1、使用OCR1A作为TOP值:WGM[13:10] = 0100 说明: TCNT1加计数到TCNT1 = OCR1A时,比较匹配A发生、OC1A引脚电平翻转,同时TCNT1会被清0。 TCNT1加计数到TCNT1 = OCR1B时,比较匹配B发生、 OC1B引脚电平翻转。 但是,如果OCR1A < OCR1B,那么因为在TCNT1 = OCR1A时、TCNT1会被清0,不会继续增加到更大的OCR1B, 所以OCF1B永远不会发生、OC1B引脚将永远不会翻转。 测试代码: Drv_Timer.c中增加1个初值设置函数和2个中断服务函数: // ========================================================================================================== // 设置TCNT1、OCR1A、OCR1B的值 // // (1). 在比较匹配下、OCR1A、OCR1B需要在TCNT1被设置之后设置 // 相应的,ICP1也需要在TCNT1被设置之后设置 // // ==========================================================================================================
上一篇:B001-Atmega16-看门狗WDT-(ques=1)
下一篇:B001-Atmega16-定时器2-(ques=4)
推荐阅读最新更新时间:2024-11-10 10:43
推荐帖子
- UBOOT , NBOOT EBOOT 三者有什么区别?
- UBOOT,NBOOTEBOOT三者有什么区别UBOOT,NBOOTEBOOT三者有什么区别?搜索老帖子吧。回答很多次了,UBOOT是什么东东?好像只在Linux下听说过,CE下有这个吗?bootloader与linux,wince之类操作系统是可以完全分开的,只不过wince和eboot联系比较紧密,实际上bootloader应该与系统完全不相关才好uboot在linux下有这个说法,并且在XXX网站有下载。nboot就是在2440/2410等的内部SRAM执行的
- zl0801 嵌入式系统
- 请问有没有支持redhat9的无线网卡啊
- 请问有没有支持redhat9的无线网卡啊,我在市场上找的全部都是支持Windows的请问有没有支持redhat9的无线网卡啊对于CiscoAironet的无线网卡Redhat8.0支持很好USB接口的吗?不知,帮顶没遇到过这种情况.
- oneforlove 嵌入式系统
- 预测: 3个二极管叫“一种超大电流直流防反接电路”
- 预测:3个二极管叫“一种超大电流直流防反接电路”还是发明专利,,,服了 除了是发明专利以外,申请人可是正经的科技有限公司,由不得你不服。不可能过初审的 不可能过初审的该公司要是申请个实用新型呢?那就过去了,然后就授权了。发明专利,初审可能能过,但过不去实审。实审可是要先交实审费的。特意看了下,两个专利都是无权-视为撤回状态,这两个专利要是通过了实在说不过去这个很多时候是被迫的,有些公司为申请ZF高新产业
- PowerAnts 电路观察室
- 请教一个关于stm32用JLINK烧写的问题
- keilMDKV3.7+JLINKV8,cpu为STM32F103ZE,程序下载时提示:Flashdownloadfailed-Cortex-M3。这是什么原因呢?请教一个关于stm32用JLINK烧写的问题看来这真的是个普遍问题,不知为什么不能引起版主注意呢?我被这个问题折磨了一个星期了。今天终于有了进展!! 我一直是用mdk+ulink2,用的好好的,前段时间有几个星期没有用,再用发现ulink2坏了,usb无法找到设备,找买家,已经过期了,买家让
- pfxu stm32/stm8
- 如何确保PCB设计信号完整性
- 信号完整性是指信号在信号线上的质量,即信号在电路中以正确的时序和电压作出响应的能力。如果电路中信号能够以要求的时序、持续时间和电压幅度到达接收器,则可确定该电路具有较好的信号完整性。反之,当信号不能正常响应时,就出现了信号完整性问题。随着高速器件的使用和高速数字系统设计越来越多,系统数据率、时钟速率和电路密集度都在不断地增加。在这种设计中,系统快斜率瞬变和工作频率很高,电缆、互连、印制板(PCB)和硅片将表现出与低速设计截然不同的行为,即出现信号完整性问题。信号完整性问题能导致或
- jdbpcb00 PCB设计
- 《CMake 构建实战-项目开发卷》分享1—编译构建基础
- 《CMake构建实战-项目开发卷》分享1编译构建基础导言本书第一章《构建之旅》,从命令行编译源程序,从程序由单一文件构成,到多个文件构成,再到程序连接到静态库文件,程序链接到动态库文件,非常详细的描述了目标构建的关系、构建书序。最后引入Boost库,构建一个依赖于第三方库的程序。回首我的嵌入式开发历史,吃了多少编译的亏,吭哧吭哧解决了多少编译相关的错误,但是没有形成一个系统的知识架构,非常遗憾。感谢本书作者为我补全了编译相关的一些知识。浅谈Makefile
- CoderX9527 编程基础
设计资源 培训 开发板 精华推荐
- TCR5SB27U、200mA、2.7V输出电压CMOS低压降稳压器的典型应用
- 用于电池充电器的 1.8V、2.5V DC 至 DC 单路输出电源
- 使用基于 LTC4162IUFD-LAD USB PD(C 电缆)的电池充电器和电源路径的典型应用
- LT1117CM 高效双路线性电源的典型应用
- LTC3707-SYNC 的典型应用 - 高效率、两相同步降压型开关稳压器
- 具有可编程扩频和可调 RSTB 的 NCV890204 2A、2MHz 汽车降压开关稳压器的典型应用
- 多模GPS定位板
- EPT1020xS,QorIQ PowerPC 板,紧凑、经济高效且功能强大的平台,用于开发高性能网络控制设备
- CRD-5FF0912P,用于 7L D2PAK 的 SiC MOSFET 高频评估板
- 板板板*