1、基于Atmega8的频率计原程序基于Atmega8的频率计原程序图基于Atmega8单片机的频率计基于Atmega8单片机的频率计前言:Atmega8-是8位AVR单片机,(8-Kbyte self-programming Flash Program Memory, 1-Kbyte SRAM, 512 Byte EEPROM, 6 or 8 Channel 10-bit A/D-converter. Up to 16 MIPS throughput at 16 Mhz. 2.7 - 5.5 Volt operation.);Nokia 3310 LCD 实验目标 频率计是我们经常会用到的实验仪
2、器之一,本实验要使用单片机和计数电路及液晶器件来设计一个宽频的频率计。 期望达到10Hz1.1G范围的频率精确测量。 实验电路图(初步方案) 1) 计数及显示电路:此主题相关图片如下:2)前置放大及分频电路: 设计设计测量频率的思路 频率的测量实际上就是在1S时间内对信号进行计数,计数值就是信号频率。用单片机设计频率计通常采用两种办法,1)使用单片机自带的计数器对输入脉冲进行计数,或者测量信号的周期;2)单片机外部使用计数器对脉冲信号进行计数,计数值再由单片机读取。 由于单片机自带计数器输入时钟的频率通常只能是系统时钟频率的几分之一甚至几十分之一,因此采用单片机的计数器直接测量信号频率就受到了
3、很大的限制。 本实验电路采用方式2,使用一片 74LS393四位双二进制计数器和Atmega8的T1计数器组成了24位计数器,最大计数值为16777215。如果输入信号经过MB501分频器进行64分频后再进行测量,则固定1S时基下最高测量频率为1073.741760Mhz。 为了方便得到准确的1秒钟测量闸门信号,我们使用了Atmega8的异步实时时钟功能,采用32.768Khz的晶振由TC2产生1秒钟的定时信号。 测量频率原理: 单片机打开测量闸门,即PB1输出高电平,同时TC2定时器启动。74LS393开始对输入脉冲进行计数,74LS393每计数达256时,Atmega8的T1计数器也向上计
4、数1次。当1S 定时到达时,单片机产生中断,PB1输出低电平关闭测量闸门,然后Atmega8读取74LS393和T1的计数值,然后送LCD显示。 实验进展 2004-09-27 根据设计思路编写程序初步获得了一些实验结果,如下图所示。下图是测量8M有源晶振的输出结果。此主题相关图片如下:由于1S的测量闸门时间在业余条件下不好测试,因此,实验程序中在LCD上同时显示实时时钟用于判断1S闸门时间的准确*。实验中,我使用CDMA手机上显示的GPS卫星精确时间进行比较。手机时间显示的最小单位是分钟,测量时一旦手机分钟值发生跳变,则立即记录下LCD显示的秒值,这样的话让频率计运行一段时间后,再多次记录下
5、LCD显示的秒,就可以准确判断频率计的异步时钟是否准确。实验过程中,我让频率计走了10个小数左右,测量的1S时钟还是非常准确的。实验源程序频率测量源代码:#include #include #include lcd.h #include bmp.h unsigned long counter; unsigned char countlow; unsigned char fre=00.000000; unsigned char time=00:00:00; #pragma interrupt_handler timer2_ovf_isr:iv_TIMER2_OVF void timer2_ovf
6、_isr(void) unsigned char i; /TCCR2=0; PORTB &= 0X02; /关闭闸门 /读取计数值 counter = TCNT1; /读取T/C1计数值(频率值的高16位) counter = counter*256; /计算频率值的高16位 countlow = (PIND & 0b11000000)|(PINC & 0b00111111); /读取计数值的低8位 counter = counter + countlow; /计算频率值 PORTD |= 0X01; /74LS393清零 TCNT1 = 0; PORTD &= 0X01; /关闭清零 TCN
7、T2 = 0X80; /定时时间1秒 PORTB |= 0X02; /打开闸门 /实时时钟显示 time7+; fre0=counter /10000000+0x30; counter=counter %10000000; fre1=counter /1000000+0x30; counter=counter %1000000; fre3=counter /100000+0x30; counter=counter %100000; fre4=counter /10000+0x30; counter=counter %10000; fre5=counter /1000+0x30; counter
8、=counter %1000; fre6=counter /100+0x30; counter=counter %100; fre7=counter /10 + 0x30; fre8=counter %10 + 0x30; LCD_write_String(0,2,fre); LCD_draw_map(14,2,Bmp003,7,14); /显示小数点 LCD_draw_map(62,2,MHz,22,14); /显示频率单位 if ( time7 (9+0x30) ) time6 +; time7 -= 10; if ( time6 (5+0x30) ) time4 +; time6 -=
9、6; if (time4 (9+0x30) time3+; time4-=10; if (time3 (5+0x30) time1+; time3-=6; if (time1(9+0x30) time0+; time1-=10; LCD_write_String(2,4,time); LCD_draw_map(16,4,Bmp002,7,14); /显示“:”字符 LCD_draw_map(37,4,Bmp002,7,14); /*/ void main(void) unsigned char i; OSCCAL=0xA3; / 8M系统内部时钟校准 /设置MCU的I/O口 DDRB |= L
10、CD_RST | LCD_DC | LCD_CE | SPI_MOSI | SPI_CLK ; DDRB |= 0x02; /计数闸门 DDRD |= 0X01; /74LS393清零 /DDRD |= 0X08; /LED /DDRD &= 0X20; DDRC &= 0B11000000; DDRD &= 0B00111111; SPSR |= BIT(SPI2X); / 设置SPI时钟倍速 SPCR |= BIT(SPE)|BIT(MSTR); / 使能SPI接口,主机模式,4M时钟 LCD_init(); /LCD_clear(); / 清屏 LCD_draw_map(12,0,Bmp
11、001,60,13); ASSR = 1 AS2; /选择异步时钟 TCNT2 = 0X80; /定时时间1秒 TCCR2 = (1CS22)|(1CS21); /T/C2预分频比256 TIMSK |= BIT(TOIE2); /允许TC2溢出中断 TCCR1B |= BIT(CS12)|BIT(CS11)|BIT(CS10); /时钟外部T1输入,上升源驱动 SEI(); while(1) 3310液晶显示源代码:#include #include #include lcd.h #include 6x8.h #include chinese.h /*- LCD_init : 3310LCD
12、初始化 编写日期 :2004-8-10 最后修改日期 :2004-8-10 -*/ void LCD_init(void) PORTB &= LCD_RST; / 产生一个让LCD复位的低电平脉冲 delay_1us(); PORTB |= LCD_RST; PORTB &= LCD_CE ; / 关闭LCD delay_1us(); PORTB |= LCD_CE; / 使能LCD delay_1us(); LCD_write_byte(0x21, 0); / 使用扩展命令设置LCD模式 LCD_write_byte(0xc8, 0); / 设置偏置电压 LCD_write_byte(0x0
13、6, 0); / 温度校正 LCD_write_byte(0x13, 0); / 1:48 LCD_write_byte(0x20, 0); / 使用基本命令 LCD_clear(); / 清屏 LCD_write_byte(0x0c, 0); / 设定显示模式,正常显示 PORTB &= LCD_CE ; / 关闭LCD /LCD_clear(); /*- LCD_clear : LCD清屏函数 编写日期 :2004-8-10 最后修改日期 :2004-8-10 -*/ void LCD_clear(void) unsigned int i; LCD_write_byte(0x0c, 0);
14、 LCD_write_byte(0x80, 0); for (i=0; i504; i+) LCD_write_byte(0, 1); /*- LCD_set_XY : 设置LCD坐标函数 输入参数:X :083 Y :05 编写日期 :2004-8-10 最后修改日期 :2004-8-10 -*/ void LCD_set_XY(unsigned char X, unsigned char Y) LCD_write_byte(0x40 | Y, 0); / column LCD_write_byte(0x80 | X, 0); / row /*- LCD_write_char : 显示英文字
15、符 输入参数:c :显示的字符; 编写日期 :2004-8-10 最后修改日期 :2004-8-10 -*/ void LCD_write_char(unsigned char c) unsigned char line; /c -= 32; /for (line=0; line6; line+) /LCD_write_byte(font6x8cline, 1); for (line=0; line7; line+) LCD_write_byte(font7x13cline, 1); for (line=7; line14; line+) LCD_write_byte(font7x13clin
16、e, 1); /*- LCD_write_char : 英文字符串显示函数 输入参数:*s :英文字符串指针; X、Y : 显示字符串的位置 编写日期 :2004-8-10 最后修改日期 :2004-8-10 -*/ void LCD_write_String(unsigned char X,unsigned char Y,char *s) unsigned char line; unsigned char i=0; while (*s) LCD_set_XY(X+i*7,Y); for (line=0; line7; line+) LCD_write_byte(font7x13*s-0X30
17、line, 1); LCD_set_XY(X+i*7,Y+1); for (line=7; line14; line+) LCD_write_byte(font7x13*s-0X30line, 1); s+; i+; /*- LCD_write_chi: 在LCD上显示汉字 输入参数:X、Y :显示汉字的起始X、Y坐标; ch_with :汉字点阵的宽度 num :显示汉字的个数; line :汉字点阵数组中的起始行数 row :汉字显示的行间距 编写日期 :2004-8-11 最后修改日期 :2004-8-12 -*/ void LCD_write_chi(unsigned char X,
18、unsigned char Y, unsigned char ch_with,unsigned char num, unsigned char line,unsigned char row) unsigned char i,n; LCD_set_XY(X,Y); /设置初始位置 for (i=0;inum;) for (n=0; nch_with*2; n+) /写一个汉字 if (n=ch_with) /写汉字的下半部分 if (i=0) LCD_set_XY(X,Y+1); else LCD_set_XY(X+(ch_with+row)*i),Y+1); LCD_write_byte(ch
19、ina_charline+in,1); i+; LCD_set_XY(X+(ch_with+row)*i),Y); /*- LCD_write_chi: 汉字移动 输入参数:X、Y :显示汉字的起始X、Y坐标; T :移动速度; 编写日期 :2004-8-13 最后修改日期 :2004-8-13 -*/ void LCD_move_chi (unsigned char X, unsigned char Y, unsigned char T) unsigned char i,n,j=0; unsigned char buffer_h84=0; unsigned char buffer_l84=0
20、; for (i=0; i156; i+) buffer_h83 = china_chari/12j; buffer_l83 = china_chari/12j+12; j+; if (j=12) j=0; for (n=0; n83; n+) buffer_hn=buffer_hn+1; buffer_ln=buffer_ln+1; LCD_set_XY(X,Y); for (n=0; n83; n+) LCD_write_byte(buffer_hn,1); LCD_set_XY(X,Y+1); for (n=0; n83; n+) LCD_write_byte(buffer_ln,1);
21、 delay_nms(T); /*- LCD_draw_map : 位图绘制函数 输入参数:X、Y :位图绘制的起始X、Y坐标; *map :位图点阵数据; Pix_x :位图像素(长) Pix_y :位图像素(宽) 编写日期 :2004-8-13 最后修改日期 :2004-8-13 -*/ void LCD_draw_map(unsigned char X,unsigned char Y,unsigned char *map, unsigned char Pix_x,unsigned char Pix_y) unsigned int i,n; unsigned char row; if (P
22、ix_y%8=0) row=Pix_y/8; /计算位图所占行数 else row=Pix_y/8+1; for (n=0;nrow;n+) LCD_set_XY(X,Y); for(i=0; iPix_x; i+) LCD_write_byte(mapi+n*Pix_x, 1); Y+; /换行 /*- LCD_write_byte : 使用SPI接口写数据到LCD 输入参数:data :写入的数据; command :写数据/命令选择; 编写日期 :2004-8-10 最后修改日期 :2004-8-13 -*/ void LCD_write_byte(unsigned char data,
23、 unsigned char command) PORTB &= LCD_CE ; / 使能LCD if (command = 0) PORTB &= LCD_DC ; / 传送命令 else PORTB |= LCD_DC ; / 传送数据 SPDR = data; / 传送数据到SPI寄存器 while (SPSR & 0x80) = 0); / 等待数据传送完毕 PORTB |= LCD_CE ; / 关闭LCD 位图数据表unsigned char Bmp001= /*- ; 源文件 / 文字 : 频率计实验 ; 宽高(像素): 6013 ; 字模格式/大小 : 单色点阵液晶字模,纵向
24、取模,字节倒序/120字节 ; 数据转换日期 : 2004-9-23 17:39:05 -*/ 0x20,0xFC,0xE0,0x3E,0xA8,0x26,0xFA,0x0A,0xEE,0x0A,0xFA,0x00,0x84,0x8C,0x54,0xA4, 0xD4,0xAE,0xD4,0xA4,0x54,0x8C,0x04,0x00,0x20,0xE2,0x04,0x00,0x20,0x20,0x20,0xFE, 0x20,0x20,0x20,0x00,0x10,0x0C,0x44,0x94,0x24,0x06,0xF4,0x04,0x04,0x14,0x0C,0x00, 0x42,0x7A
25、,0x42,0xFE,0x20,0x90,0x28,0xA6,0x28,0x90,0x20,0x00,0x09,0x08,0x05,0x02, 0x09,0x08,0x05,0x02,0x01,0x02,0x0D,0x00,0x02,0x02,0x02,0x02,0x02,0x0F,0x02,0x02, 0x02,0x02,0x02,0x00,0x00,0x0F,0x04,0x02,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00, 0x01,0x09,0x09,0x09,0x05,0x03,0x01,0x03,0x05,0x09,0x01,0x00,0x02,0
26、x0A,0x09,0x07, 0x08,0x0B,0x08,0x0B,0x0C,0x0B,0x08,0x00 ; unsigned char MHz= /*- ; 源文件 / 文字 : MHz ; 宽高(像素): 3816 ; 字模格式/大小 : 单色点阵液晶字模,纵向取模,字节倒序/76字节 ; 数据转换日期 : 2004-9-27 14:27:15 -*/ /0x00,0xF8,0x30,0xC0,0x00, /0x00,0x00,0xC0,0x30,0xF8,0x00,0x00,0xF8,0x80,0x80,0x80,0x80,0x80,0xF8,0x00,0x00, /0x40,0x40,0x40,0xC0,0x40,0x00, /0x00,0x1F,0x00,0x00,0x07, /0x18,0x07,0x00,0x00,0x1F,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00, /0x10,0x1C,0x12,0x11,0x10,0x00 /0xF8,0x70,0xE
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1