赞
踩
一步步完成数码管
主要内容:
第一步:产生1ms的时基
第二步:静态显示
第三步:动态扫描
第四步:余晖 重影
第五步:带消息机制的任务函数
第六步:按指定进制显示
-------------------------------------------------------------------------------------------------------------------------------------
开发环境:AVR Studio 4.19 + avr-toolchain-installer-3.4.1.1195-win32.win32.x86
芯片型号:ATmega16
芯片主频:8MHz
-------------------------------------------------------------------------------------------------------------------------------------
- // -------------------
- // 定时器中断模式
- 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
- {
- COM_MODE_NONE = 0,
- COM_MODE_TOGGLE = 1,
- COM_MODE_CLEAR = 2,
- COM_MODE_SET = 3,
- } TIMER_COM_MODE;
-
- // 定时器0
- typedef enum
- {
- T0_WGM_NOMAL = 0,
- T0_WGM_PHASE_PWM = 1,
- T0_WGM_CTC = 2,
- T0_WGM_FAST_PWM = 3,
-
- T0_CLK_SOURCE_NONE = 0,
- T0_CLK_SOURCE_CLK_1 = 1,
- T0_CLK_SOURCE_CLK_8 = 2,
- T0_CLK_SOURCE_CLK_64 = 3,
- T0_CLK_SOURCE_CLK_256 = 4,
- T0_CLK_SOURCE_CLK_1024 = 5,
- T0_CLK_SOURCE_T0_FALL = 6,
- T0_CLK_SOURCE_T0_RAISE = 7
- } TIMER0_MODE;
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Drv_Timer.c中的操作函数:
- // ==========================================================================================================
- // TIMER0 初始化
- //
- // 参数:wave_mode 工作模式/波形产生模式选择
- // OC_mode 比较匹配/PWM输出模式选择
- // clk_source 时钟源和预分频选择
- //
- // 写TCCR0时需要清除bit7=FOC0
- //
- // 定时器溢出周期 T = ((1.0 / 8000000) * 1000000) * clk_source * 256 ( @ 8MHz )
- // ==========================================================================================================
- void Drv_Timer0_init(const uint8_t wave_mode, const uint8_t com_mode, const uint8_t clk_source)
- {
- uint8_t wgm00,wgm01;
-
- wgm00 = wave_mode & 0x01;
- wgm01 = (wave_mode & 0x02) >> 1;
-
- // 写TCCR0时需要将bit7=FOC0清0
- TCCR0 = (wgm00 << 6)| // 工作模式/波形产生模式选择
- (wgm01 << 3)|
- ((com_mode & 0x03) << 4)| // 比较匹配/PWM输出模式选择
- ((clk_source & 0x07) << 0); // 时钟源和预分频选择
- }
-
- // ==========================================================================================================
- // TIMER0 中断使能
- //
- // 参数:int_mode = INT_MODE_TOV 或 INT_MODE_OCF 或 INT_MODE_ICF
- // enable = ENABLE 或 DISABLE
- //
- // 说明:
- // 1、OC0引脚要先配置成比较匹配引脚、再修改数据方向寄存器DDB3
- // 2、可以单独使能/禁止一种模式的中断
- //
- // ==========================================================================================================
- void Drv_Timer0_INT_Enable(const uint8_t int_mode, const uint8_t enable)
- {
- if(INT_MODE_TOV == int_mode)
- {
- if(DISABLE == enable)
- {
- TIMSK &= ~(1 << TOIE0);
- }
- else
- {
- TIMSK |= (1 << TOIE0);
- }
- TIFR |= (1 << TOV0);
- return ;
- }
- if(INT_MODE_OCF == int_mode)
- {
- if(DISABLE == enable)
- {
- TIMSK &= ~(1 << OCIE0);
- }
- else
- {
- TIMSK |= (1 << OCIE0);
- }
- TIFR |= (1 << OCF0);
- }
- }
-
- // ==========================================================================================================
- // 设置TCNT0和OCR0的值
- //
- // (1). 在比较匹配下、OCR0需要在TCNT0被设置之后设置
- // ==========================================================================================================
- void Drv_Timer0_set_TCNT0_OCR0(const uint8_t tcnt0, const uint8_t ocr0)
- {
- TCNT0 = tcnt0;
- OCR0 = ocr0;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
sys_timer.c中设置定时器0,并在OCF0中断中使用PA1测试定时时间:
- #include <avr/interrupt.h>
- #include "Drv_Timer.h"
- #include "sys_timer.h"
-
- // ==========================================================================================================
- // 系统任务定时器
- //
- // (1). 使用Timer0产生1ms的时标
- // 定时周期 T = ((1.0/8000000)*1000000)*64*(124+1) = 1000us = 1ms
- //
- // ==========================================================================================================
- void sys_timer_init(void)
- {
- // 定时器0初始化:CTC模式、OC0引脚不连接、64预分频
- Drv_Timer0_init(T0_WGM_CTC, COM_MODE_NONE, T0_CLK_SOURCE_CLK_64);
- // 设置初值:TCNT0=0、OCR0=122
- Drv_Timer0_set_TCNT0_OCR0(0, 122);
- // 使能OCF0中断
- Drv_Timer0_INT_Enable(INT_MODE_OCF, ENABLE);
- }
-
- // ==========================================================================================================
- // 系统定时器中断
- //
- // (1). 使用Timer0的CTC中断调度各个任务
- //
- // ==========================================================================================================
- ISR(TIMER0_COMP_vect)
- {
- PORTA ^= (1 << PA1); // 使用PA1测试定时周期
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
main.c中完成初始化,并设置IO:
- // ==========================================================================================================
- // 主函数
- // ==========================================================================================================
- #include <avr/io.h>
- #include "Drv_Timer.h"
- #include "system.h"
- #include "sys_timer.h"
- #include "config.h"
-
- // ==========================================================================================================
- // main函数
- // ==========================================================================================================
- int main(void)
- {
- // ---------
- // 关全局中断
- cli();
-
- // 系统初始化 ( 包含sys_timer_init() )
- sys_init();
-
- DDRA |= (1 << DDA0) | (1 << DDA1);
- PORTA &= ~((1 << PA0 ) | (1 << PA1 ));
-
- // OC0/PB3初始化为输出0
- DDRB |= (1 << DDB3);
- PORTB &= ~((1 << PB3 ));
-
- // 开全局中断
- sei();
-
- // ---------
- while(1)
- {
- }
- return 0;
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
1、这一步需要根据电路图、在指定的数码管上显示指定的符号。
电路中使用的是共阴极数码管:
1个数码管有8个LED,称为8段数码管。
</
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。