完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
这是曾经本科生时期的制作,一个用atmega8a芯片做的测速计。当时选用atmega8a的原因很简单,学生时代做东西,都是捡到啥芯片就用啥,只要性能还能过得去就可以了。这款单片机性能一般,但是比at89c51强多了(最主要是剩下的多),就是烧写程序时候需要配置熔丝位,一时间不太习惯。整个工程是用iar for avr写的,因为那时候一直用msp430,习惯了iar的界面。
首先是选头文件,iom8.h定义了相关的寄存器,装好iar就能用了。 //这里是iar里面的 #include #include //后面是自己的 #include"bianliangshengming.h" #include"hanshushengming.h" #include"hanshudingyi.h" #include"lcd.h" #include"int.h" 主函数就这么写了,主要是一堆初始化,最后一个while(1),主要程序都是在中断里面,因为检测只有在外界触发了传感器才需要进行。 void main(void) { init_devices(); timer1_init(); lcd(); timer0_init(); while(count2<10000) { if(anjian==0) { DelayNms(3); if(anjian==0); { key=1; while(anjian==0); break; } } } count2=0; TCCR0=0x00; lcd1(); timer0_init(); while(count2<30000) { } TCCR0=0x00; TCCR1B=0X00; led0=0; led1=0; count2=0; timer2_init(); if(!key)//选择模式,当时有两个检测模式,算法不太一样,具体不记得了 { LcdWriteCom(0x01); LCD_write_string(0,1,"MODE1 Running....."); } else { LcdWriteCom(0x01); LCD_write_string(0,1,"MODE2 Running....."); } timer0_init(); while(count2<5000) { } TCCR0=0x00; int_init(); // DelayNms(5000); timer1_init(); while(1) { __no_operation(); } } 一系列的外设初始化写在另一个文件,用了1602作为显示,这些初始化代码专门写一个文件。 #ifndef __LCD_H_ #define __LCD_H_ /********************************** 当使用的是4位数据传输的时候定义, 使用8位取消这个定义 **********************************/ #define LCD1602_4PINS 1 /********************************** 包含头文件 **********************************/ //---重定义关键词---// #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif /********************************** PIN口定义 **********************************/ #define LCD1602_DATAPINS PORTC #define LCD1602_E PORTC_Bit4 #define LCD1602_RW PORTD_Bit5 #define LCD1602_RS PORTB_Bit0 #endif /*void Lcd1602_Delay1ms(unsigned int ms) { unsigned int i; for(;ms>0;ms--) for(i=0;i<2*4*143;i++); }*/ /******************************************************************************* * 函 数 名 : LcdWriteCom * 函数功能 : 向LCD写入一个字节的命令 * 输 入 : com * 输 出 : 无 *******************************************************************************/ #ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时 void LcdWriteCom(uchar com) //写入命令 { LCD1602_E = 0; //使能 LCD1602_RS = 0; //选择发送命令 //LCD1602_RW = 0; //选择写入 LCD1602_DATAPINS = com; //放入命令 DelayNms(1); //等待数据稳定 LCD1602_E = 1; //写入时序 DelayNms(5); //保持时间 LCD1602_E = 0; } #else void LcdWriteCom(uchar com) //写入命令 { LCD1602_E = 0; //使能清零 LCD1602_RS = 0; //选择写入命令 //LCD1602_RW = 0; //选择写入 LCD1602_DATAPINS = com>>4; //由于4位的接线是接到P0口的低四位,所以传送高四位用改 DelayNms(1); LCD1602_E = 1; //写入时序 DelayNms(5); LCD1602_E = 0; // Lcd1602_Delay1ms(1); LCD1602_DATAPINS = com ; //发送低四位 DelayNms(1); LCD1602_E = 1; //写入时序 DelayNms(5); LCD1602_E = 0; } #endif /******************************************************************************* * 函 数 名 : LcdWriteData * 函数功能 : 向LCD写入一个字节的数据 * 输 入 : dat * 输 出 : 无 *******************************************************************************/ #ifndef LCD1602_4PINS void LcdWriteData(uchar dat) //写入数据 { LCD1602_E = 0; //使能清零 LCD1602_RS = 1; //选择输入数据 LCD1602_RW = 0; //选择写入 LCD1602_DATAPINS = dat; //写入数据 DelayNms(1); LCD1602_E = 1; //写入时序 DelayNms(5); //保持时间 LCD1602_E = 0; } #else void LcdWriteData(uchar dat) //写入数据 { LCD1602_E = 0; //使能清零 LCD1602_RS = 1; //选择写入数据 //LCD1602_RW = 0; //选择写入 LCD1602_DATAPINS = dat>>4; //由于4位的接线是接到P0口的低四位,所以传送高四位用改 DelayNms(1); LCD1602_E = 1; //写入时序 DelayNms(5); LCD1602_E = 0; LCD1602_DATAPINS = dat ; //写入低四位 DelayNms(1); LCD1602_E = 1; //写入时序 DelayNms(5); LCD1602_E = 0; } #endif /******************************************************************************* * 函 数 名 : LcdInit() * 函数功能 : 初始化LCD屏 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ #ifndef LCD1602_4PINS void LcdInit() //LCD初始化子程序 { LcdWriteCom(0x38); //开显示 LcdWriteCom(0x0c); //开显示不显示光标 LcdWriteCom(0x06); //写一个指针加1 LcdWriteCom(0x01); //清屏 LcdWriteCom(0x80); //设置数据指针起点 } #else void LcdInit() //LCD初始化子程序 { LcdWriteCom(0x32); //将8位总线转为4位总线 LcdWriteCom(0x28); //在四位线下的初始化 LcdWriteCom(0x0c); //开显示不显示光标 LcdWriteCom(0x06); //写一个指针加1 LcdWriteCom(0x01); //清屏 LcdWriteCom(0x80); //设置数据指针起点 } #endif void LCD_set_xy( unsigned char x, unsigned char y ) //写地址函数 { unsigned char address; if (y == 0) address = 0x80 + x; // 最高位是1,另七位才是地址 故有+0x80 else if(y==1) address = 0xc0 + x; else if(y==2) address=0x80+x+0x14; else address=0xc0+x+0x14; LcdWriteCom( address); } void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s) //列x=0~15,行y=0,1 { LCD_set_xy( X, Y ); //写地址 while (*s) // 写显示字符 { LcdWriteData( *s ); s ++; } } void LCD_write_mode(unsigned char X,unsigned char Y,unsigned long int count) { uchar D[7]; count/=100; D[6]=0; D[5]='s'; D[4]=count%10+48; D[2]=(count%100)/10+48; D[1]=(count%1000)/100+48; D[0]=(count%10000)/1000+48; D[3]='.'; LCD_write_string(X,Y,D); } 相关的定时器等配置如下 #include void lcd(void) { DelayNms(50); LCD_write_string(0,0,"10s choose mode"); } void lcd1(void) { DelayNms(50); LCD_write_string(0,0,"Speedtest will start"); // DelayNms(20); LCD_write_string(0,1," after 30 seconds "); //DelayNms(2000); } /**************延时Nms*************************/ void DelayNms(unsigned int ms) { unsigned int i; for(;ms>0;ms--) for(i=0;i<4*143;i++); } //定时器T0初始化,计时0.5ms void timer0_init(void) { TCCR0 = 0x00;//停止定时器 TCNT0 = 0x83;//初始值 TIMSK |= 0x01;//中断允许 TCCR0 = 0x03;//启动定时器 } //外中断初始化 /*void int_init(void) { MCUCR |= 0x0A;//int0 int1 下降沿中断 MCUCSR|= 0x00; PORTD|=(1< } */ void int_init(void) { MCUCR |= 0x02;//int0 下降沿中断 MCUCSR|= 0x00; PORTD|=(1< } void init_devices(void) { __disable_interrupt(); //禁止所有中断 MCUCR = 0x00; MCUCSR = 0x80;//禁止JTAG GICR = 0x00; Portinit(); LcdInit(); __enable_interrupt(); }//开全局中断 void Portinit(void) { DDRC=0XFF; DDRB=0XFF; PORTC=0XFF; DDRD=0Xff; PORTD=0XFF; } void timer1_init(void) { DDRB=0XFF; TCCR1A=0XF2; TCCR1B=0X19; OCR1A= 0x32;//匹配A值 OCR1B = 0x32;//匹配B值 ICR1 = 0x64;//输入捕捉匹配值 } void timer2_init(void) { TCCR2 = 0x00;//停止定时器 ASSR = 0x00;//异步时钟模式 TCNT2 = 0x83;//初始值 TIMSK |= 0x40;//中断允许 TCCR2 = 0x03;//启动定时器 } void end(void) { TCCR0 = 0x00; LcdWriteCom(0x01); GICR_Bit6=0; } 中断程序用来计时 #pragma vector=INT0_vect __interrupt void INT0_Server(void)// 传感器停止计时 { if(key){ if(!s) { TCNT0 = 0x83; count2=count1; s=1; } else { end(); unsigned long int count3; count3=count1+5*count1-5*count2; LCD_write_string(0,0,"T1:"); LCD_write_mode(5,0,count2); LCD_write_string(0,1,"T2:"); LCD_write_mode(5,1,count1); LCD_write_string(0,2,"Time:"); LCD_write_mode(0,3,count3); } } else { end(); LCD_write_string(0,0,"Time:"); LCD_write_mode(0,1,count1); } } #pragma vector=TIMER0_OVF_vect __interrupt void TIMER0_OVF_Server(void) { TCNT0 = 0x83; count2+=2; } #pragma vector=TIMER2_OVF_vect __interrupt void TIMER2_OVF_Server(void) { TCNT2 = 0x83; count1+=1; } 这个功能还是很简单的。 |
|
|
|
只有小组成员才能发言,加入小组>>
2548 浏览 0 评论
1146浏览 2评论
745浏览 1评论
499浏览 0评论
265浏览 0评论
427浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 01:16 , Processed in 1.498449 second(s), Total 78, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号