完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
实验名称:利用定时器T1实现定时1S的实验
功能描述:利用定时器T1实现1S定时,数码管显示秒数。 实验目的:学会使用定时器T1进行定时。 学会使用数码管显示数据。 学习定时器中断。 实验说明:MCU–M128 内部8M晶振 如果数码管刷新频率不够高的话将会出现闪烁的现象。 /************************************************ 文件:main.c 用途: 注意:内部8M晶振 ************************************************/ #include “config.h” volatile unsigned int countnum=0; void timer1_init(void) { TCCR1B = 0x00; //stop TCNT1H = 0x8F; //setup TCNT1L = 0x81; OCR1AH = 0x70; OCR1AL = 0x7F; OCR1BH = 0x70; OCR1BL = 0x7F; OCR1CH = 0x70; OCR1CL = 0x7F; ICR1H = 0x70; ICR1L = 0x7F; TCCR1A = 0x00; TCCR1B = 0x04; //start Timer } #pragma interrupt_handler timer1_ovf_isr:15 void timer1_ovf_isr(void) { TCNT1H = 0x8F; //reload counter high value TCNT1L = 0x81; //reload counter low value countnum++; if(countnum》9999) countnum=0; } void init_devices(void) { CLI(); //disable all interrupts timer1_init(); TIMSK = 0x04; //timer interrupt sources SEI(); //re-enable interrupts } void main(void) { init_devices(); HC_595_init(); while(1) { Seg7_Led_display(countnum); //Seg7_Led_float(25.13); } } 首先,countnum用以在中断中计数1~9999(因为有四个数码管) 其数字进入的是Seg7_Led_display()函数如下: /************************************************ 文件:hc595.c 用途: 注意:内部8M晶振 ************************************************/ #include “config.h” const unsigned char Seg7_Data[]={0x3F,0x06,0x5B,0x4F,0x66, //0,1,2,3,4 0x6D,0x7D,0x07,0x7F,0x6F, //5,6,7,8,9 0x77,0x7C,0x39,0x5E,0x79,0x71,0x00}; //a,b,c,d,e,f volatile unsigned char Seg7_Led_Buf[4],point=0,point_pos=0;//point是小数点标志1代表有小数点point_pos表示小数点位置 /************************************************************************* ** 函数名称:HC595初始化 ** 功能描述: ** 输 入: ** 输出 : ** 全局变量: ** 调用模块: ** 说明: ** 注意: **************************************************************************/ void HC_595_init(void) { OE_DDR |= (1《《OE); OE_PORT &= (1《《OE); PORTB = 0x0F; spi_init(); Seg7_Led_Buf[0]=16; Seg7_Led_Buf[1]=16; Seg7_Led_Buf[2]=16; Seg7_Led_Buf[3]=16; } /************************************************************************* ** 函数名称:HC595送数据 ** 功能描述: ** 输 入: ** 输出 : ** 全局变量: ** 调用模块: ** 说明: ** 注意: **************************************************************************/ void HC_595_OUT(unsigned char data) { SS_L(); SPI_MasterTransmit(data); SS_H(); } /************************************************************************* ** 函数名称:HC595刷新显示 ** 功能描述: ** 输 入: ** 输出 : ** 全局变量: ** 调用模块: ** 说明: ** 注意: **************************************************************************/ void Seg7_Led_Update(void) { HC_595_OUT(Seg7_Data[Seg7_Led_Buf[0]]); Seg7_Bit0_En(); delay_nus(60); Seg7_Bit0_Dis(); HC_595_OUT(Seg7_Data[Seg7_Led_Buf[1]]); if((point==1)&&(point_pos==1)) HC_595_OUT((Seg7_Data[Seg7_Led_Buf[1]])|(1《《dp)); Seg7_Bit1_En(); delay_nus(60); Seg7_Bit1_Dis(); HC_595_OUT(Seg7_Data[Seg7_Led_Buf[2]]); if((point==1)&&(point_pos==2)) HC_595_OUT((Seg7_Data[Seg7_Led_Buf[2]])|(1《《dp)); Seg7_Bit2_En(); delay_nus(60); Seg7_Bit2_Dis(); HC_595_OUT(Seg7_Data[Seg7_Led_Buf[3]]); if((point==1)&&(point_pos==3)) HC_595_OUT((Seg7_Data[Seg7_Led_Buf[3]])|(1《《dp)); Seg7_Bit3_En(); delay_nus(60); Seg7_Bit3_Dis(); } /************************************************************************* ** 函数名称:Hc595显示整形数据 ** 功能描述: ** 输 入:0~9999 ** 输出 : ** 全局变量: ** 调用模块: ** 说明: ** 注意: **************************************************************************/ void Seg7_Led_display(unsigned int data) { if(data》9999) //错误处理,超出显示范围则全亮 { HC_595_OUT(0xFF); Seg7_Bitselect_PORT|=((1《《Seg7_Bit0)|(1《《Seg7_Bit1)|(1《《Seg7_Bit2)|(1《《Seg7_Bit3)); } else if(data》999) { Seg7_Led_Buf[3]=data/1000; Seg7_Led_Buf[2]=(data%1000)/100; Seg7_Led_Buf[1]=(data%100)/10; Seg7_Led_Buf[0]=data%10; Seg7_Led_Update(); } else if(data》99) { Seg7_Led_Buf[3]=16; Seg7_Led_Buf[2]=(data%1000)/100; Seg7_Led_Buf[1]=(data%100)/10; Seg7_Led_Buf[0]=data%10; Seg7_Led_Update(); } else if(data》9) { Seg7_Led_Buf[3]=16; Seg7_Led_Buf[2]=16; Seg7_Led_Buf[1]=(data%100)/10; Seg7_Led_Buf[0]=data%10; Seg7_Led_Update(); } else { Seg7_Led_Buf[3]=16; Seg7_Led_Buf[2]=16; Seg7_Led_Buf[1]=16; Seg7_Led_Buf[0]=data%10; Seg7_Led_Update(); } } /************************************************************************* ** 函数名称:HC595显示浮点数据 ** 功能描述: ** 输 入: ** 输出 : ** 全局变量: ** 调用模块: ** 说明: ** 注意: **************************************************************************/ void Seg7_Led_float(float data) { unsigned int temp; /* 重要说明:data+=0.00001;其中0.00001为容错值 解决float数据类型在计算机内部存储的误差问题,可以解决显示问题 但是会引入新的计算误差,如果精度要求大于0.00001建议更改容错值或者将此处注释掉 */ data+=0.00001; point=1; if(data》999) //错误处理,超出显示范围则全亮 { HC_595_OUT(0xFF); Seg7_Bitselect_PORT|=((1《《Seg7_Bit0)|(1《《Seg7_Bit1)|(1《《Seg7_Bit2)|(1《《Seg7_Bit3)); } else if(data》99) { temp=data*10; point_pos=1; Seg7_Led_Buf[3]=temp/1000; Seg7_Led_Buf[2]=(temp%1000)/100; Seg7_Led_Buf[1]=(temp%100)/10; Seg7_Led_Buf[0]=temp%10; Seg7_Led_Update(); } else if(data》9) { temp=data*100; point_pos=2; Seg7_Led_Buf[3]=temp/1000; Seg7_Led_Buf[2]=(temp%1000)/100; Seg7_Led_Buf[1]=(temp%100)/10; Seg7_Led_Buf[0]=temp%10; Seg7_Led_Update(); } else { temp=data*1000; point_pos=3; Seg7_Led_Buf[3]=temp/1000; Seg7_Led_Buf[2]=(temp%1000)/100; Seg7_Led_Buf[1]=(temp%100)/10; Seg7_Led_Buf[0]=temp%10; Seg7_Led_Update(); } point=0; } Seg7_Led_Buf[]字符被提取存入这个数组中,随后执行刷新数码管的Seg7_Led_Update();函数用以显示数字: 这个函数是关键: void Seg7_Led_Update(void) { HC_595_OUT(Seg7_Data[Seg7_Led_Buf[0]]); Seg7_Bit0_En(); delay_nus(60); Seg7_Bit0_Dis(); HC_595_OUT(Seg7_Data[Seg7_Led_Buf[1]]); if((point==1)&&(point_pos==1)) HC_595_OUT((Seg7_Data[Seg7_Led_Buf[1]])|(1《《dp)); Seg7_Bit1_En(); delay_nus(60); Seg7_Bit1_Dis(); HC_595_OUT(Seg7_Data[Seg7_Led_Buf[2]]); if((point==1)&&(point_pos==2)) HC_595_OUT((Seg7_Data[Seg7_Led_Buf[2]])|(1《《dp)); Seg7_Bit2_En(); delay_nus(60); Seg7_Bit2_Dis(); HC_595_OUT(Seg7_Data[Seg7_Led_Buf[3]]); if((point==1)&&(point_pos==3)) HC_595_OUT((Seg7_Data[Seg7_Led_Buf[3]])|(1《《dp)); Seg7_Bit3_En(); delay_nus(60); Seg7_Bit3_Dis(); } 比如,HC_595_OUT(Seg7_Data[Seg7_Led_Buf[0]]); 中,Seg7_Data[Seg7_Led_Buf[0]]将数字转换成段选码(控制数码管显示什么数字的),随后进入HC_595_OUT(Seg7_Data[Seg7_Led_Buf[0]]);中: 这个函数将段选的数据送给spi的寄存器: void HC_595_OUT(unsigned char data) { SS_L(); SPI_MasterTransmit(data); SS_H(); } 这里用以上原理图来解释上面的函数,首先,PB0电平先拉低再置高的目的:使74HC595在上升沿的时候将数据锁到O0-O7数据输出口。 SPI_MasterTransmit(data);这段函数出自spi.c: /************************************************ 文件:spi.c 用途:SPI驱动 ************************************************/ #include “config.h” /************************************************************************* ** 函数名称: spi_init(void) ** 功能描述: SPI初始化 ** 输 入: ** 输出 : ** 全局变量: 无 ** 调用模块: ** 说明: ** 注意: **************************************************************************/ void spi_init(void) { DDRB |= (1《《MOSI)|(1《《SCK)|(1《《SS);//设置MOSI,SCK输出 SPCR = (1《《SPE)|(1《《MSTR)|(1《《SPR0)|(1《《SPR1);//使能SPI,主机模式 } /************************************************************************* ** 函数名称: SPI_MasterTransmit(char Data) ** 功能描述: SPI主机发送数据 ** 输 入: Data 需要通过SPI传输的数据 ** 输出 : ** 全局变量: 无 ** 调用模块: ** 说明: ** 注意: **************************************************************************/ void SPI_MasterTransmit(char Data) { /* 启动数据传输 */ SPDR = Data; /* 等待传输结束 */ while(!(SPSR & (1《《SPIF))) ; } void SPI_MasterTransmit(char Data)的作用:将刚刚的段选码数据存入SPDR寄存器,然后由以上一点所述,将数据锁到O0-O7数据输出口后,数据输出则为数码管数字的具体显示。(简而言之,就是,74H595作用是将spi的串行通信的数据变成并行) 最后,是位选的选择: 比如,第一个数码管的,宏定义: #define Seg7_Bit0_En() {Seg7_Bitselect_DDR|=(1《《Seg7_Bit0);Seg7_Bitselect_PORT|=(1《《Seg7_Bit0);} #define Seg7_Bit0_Dis() {Seg7_Bitselect_DDR|=(1《《Seg7_Bit0);Seg7_Bitselect_PORT&=~(1《《Seg7_Bit0);} 即置高PB4-PB7任意一个则会使三极管导通,从而使数码管工作。 |
|
|
|
只有小组成员才能发言,加入小组>>
2561 浏览 0 评论
1159浏览 2评论
762浏览 1评论
515浏览 0评论
271浏览 0评论
448浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 19:49 , Processed in 1.496584 second(s), Total 80, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号