|
本帖最后由 machao 于 2012-11-8 23:27 编辑
贴上实验二中的2个参考代码
在实验板上设计一个采用外部中断方式的6位数码管(分、秒、1%秒各占2位)显示的简易秒表系统。可以先使用CVAVR中的程序生成向导功能进行配置,然后在它生成的程序框架基础上完成定时器中断部分程序。该系统程序设计可参考demo_7_2.c,在这个基础上修改代码,最终设计出一个完整的秒表系统。
提示:使用Mega16两个外部中断源INT0和INT1。将其中一个外部中断源与板上500Hz的标准频率相连,另外的一个外部中断源与一个按键相连。500Hz的标准频率被作为秒表系统的计时基准。按键的起到了“开始/停止/清零”作用。上电后,数码管显示全零,第一次按键,表示秒表计时开始,数码管显示的数值按1%秒速率计时。第二次按键计时停止,数码管显示最终的计时时间。第三次按键对数码管清零。以上功能可反复执行。
/*********************************************
Chip type: ATmega16
Program type: Application
Clock frequency: 4.000000MHz
Memory model: Small
External SRAM: 0
Data Stack size: 256
*********************************************/
#include <mega16.h>
flash unsigned char led_7[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
flash unsigned char position[6]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
unsigned char time[3]; //时、分、秒计数单元
unsigned char dis_buff[6]; //显示缓冲区,存放要显示的6个字符的段码值
unsigned char time_counter; //中断次数计数单元
unsigned char posit;
unsigned char key_state=0;
bit pre_pind3,int1_off,time_10ms_ok,time_20ms_ok;
void display(void) //6位LED数码管动态扫描函数
{
PORTA = led_7[dis_buff[posit]];
if (posit==2 || posit==4) PORTA |= 0x80;
PORTC = position[posit];
if (++posit>=6) posit = 0;
}
//External Interrupt 0 service routine 2ms 一次
interrupt [EXT_INT0] void ext_int0_isr(void)
{
display(); //调用LED扫描显示
if (++time_counter>=5)
{
time_counter = 0;
time_10ms_ok = 1;
}
}
//External Interrupt 1 service routine 外部按键中断
interrupt [EXT_INT1] void ext_int1_isr(void)
{
GICR = 0x7F; //关INT1中断,是做消抖处理
int1_off = 1;
pre_pind3 = 0;
if (++key_state>=3) key_state = 0;
}
void time_to_disbuffer(void) //时钟时间送显示缓冲区函数
{
unsigned char i, j=0;
for (i=0; i <= 2; i++)
{
dis_buff[j++] = time%10;
dis_buff[j++] = time/10;
}
}
void main(void)
{
PORTA=0x00; //显示控制I/O端口初始化
DDRA=0xFF;
PORTC=0x3F;
DDRC=0x3F;
PORTD = 0xFF; //PD2,PD3输入,上拉有效
time[2] = 0; time[1] = 0; time[0] = 0; //设时间初值00:00:00;
posit = 0;
time_to_disbuffer();
GICR|=0xC0; //INT1,INT0中断允许
MCUCR=0x0A; //INT1,INT0下降沿触发
#asm("sei"); //全局中断允许
while (1)
{
if (key_state == 0)
{
time[0] = 0;
time[1]=0;
time[2]=0;
time_to_disbuffer();
}
if (time_10ms_ok) //10ms到
{
time_10ms_ok=0;
time_20ms_ok=~time_20ms_ok;
if (time_20ms_ok && int1_off) //这段是间隔20ms检测按键是否释放
{ //确认释放后开INT1中断,可以接收下次的按键
if (PIND.3 && pre_pind3) //这样就防止了一次按键过程中按键抖动对INT1的影响,构成消抖功能
{
GIFR |= 0x80;
GICR |= 0x80;
int1_off = 0;
}
pre_pind3 = PIND.3;
}
if (key_state == 1)
{
if (++time[0] >= 100) //以下时间调整
{
time[0] = 0;
if (++time[1]>=60)
{
time[1] = 0;
if (++time[2]>=60) time[2] = 0;
}
}
time_to_disbuffer(); //新调整好的时间送显示缓冲区
}
}
}
}
==============================================================================================
3.(有能力同学完成)参考书中例6.7,和demo_6_7.c,设计一个8X8点阵LED广告,能够水平移动显示“<- 2月1日”。要求显示连续不闪烁,移动平稳,字符亮度均匀.
硬件连接:
PA0-JE1.8,PA1-JE1.7,...,PA7-JE1.1
PC0-JE2.1,PC1-JE2.2.........
系统时钟1M
#include <mega16.h>
#include <delay.h>
#define move_speed 8 //改变此值就可以调整左移的速度
#define bit_number 5*8 //n个字符,就只要定义成n*8,把下面的点阵定义扩大就可以了,程序不需要再动了
flash unsigned char char_7[8][5]= //采用二进制定义,可以方便的调整LED的字符点阵
{{0b00000000,0b00011100,0b00111110,0b00001000,0b01111100}, //也看的比较清楚
{0b00010000,0b00100010,0b00100010,0b00011000,0b01000100},
{0b00110000,0b00000010,0b00111110,0b00001000,0b01000100},
{0b01111111,0b00000100,0b00100010,0b00001000,0b01111100},
{0b11111111,0b00001000,0b00111110,0b00001000,0b01000100},
{0b01111111,0b00010000,0b00100010,0b00001000,0b01000100},
{0b00110000,0b00100010,0b00100110,0b00001000,0b01000100},
{0b00010000,0b00111110,0b01000010,0b00111110,0b01111100}};
char display_buff[8];
void display() //显示扫描子程序,就单一的做显示扫描,把display_buff[]的点阵送出。至于是什么,就不要管了。
{
for (k=0; k<=7; k++)
{
PORTA = display_buff[k];
PORTC = ~(1 << k);
delay_ms(2);
PORTC = 0xFF;
}
}
void main(void)
{
char gap,k0,k1,k2,number=0;
PORTA=0x00;
DDRA=0xFF;
PORTC=0xFF;
DDRC=0xFF;
while (1)
{
display();
if (++gap >= move_speed) //以下这段是关键,自己分析吧,看做了什么,有何技巧。
{
gap = 0;
for (k0=0; k0<=7; k0++)
{
k1 = number / 8;
k2 = number % 8;
display_buff[k0] = display_buff[k0] << 1;
if (char_7[k0,k1] & (0x80>>k2)) display_buff[k0] += 1;
}
if (++number >= bit_number) number = 0;
}
}
}
本段程序,执行代码大小为233字,如果要左移显示10个字符,只要将define中的bit_number定义成10*8,然后重新定义flash unsigned char char_7[8][10]和点阵(这个省不掉的,是必须做的)就可以了,执行程序的本身不需要做改动了。代码长度的增加,就仅仅为点阵定义本身增加的数量。 |
|