paper
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
测距及自动变速小车
07 级物理 小组成员:徐常春 王进光 王栋 【摘要】应用 M16 中的 I/O 接口、计数器、ADC 转换器、外部中断、PWM 等功能, 在 ICCAVR 编译环境下,设计制作出可以测距,并且能够根据行驶状态自动调节 直流电机输出功率的模型小车。
关键词: 关键词:ATMega16 ICCAVR 测距 调速
【设计目的】 : 1. 运用 ATMega16 和其他一些硬件设备,设计出带有距离测量,并可以自动 调节速度的小车。
2. 在设计和实验中加深对 I/O 端口、中断、定时(计数)器、ADC 转换及 PWM 波形发生等的学习和了解。
3. 通过设计实验进一步学习 ICCavr 的编译环境,并熟悉 AVRStudio4.0 平 台的使用。
4. 在设计的过程中锻炼团队协作能力,培养提高责任感和动手实践能力。
【硬件设备】 : Avr 单片机实验板,Mega16 芯片,LG5641BH,MMa7260,L298N,光电对管, 电容电阻及导线若干。
ATMega16 是实验教学中常见的 AVR 单片机,功能强大,本装置主要利用其 中 24 个端口控制外围电路。
LG5641BH 是四位共阳七段数码管,我们用它进行距离的显示,显示范围从 0.000 到 9999, 保证了最大的显示精度。
L298N 芯片内部集成了两个 H 桥电路, 通过改变使能端口的 PWM 波形占空比 和 IN1、IN2 端口的点平高低来实现对直流电机的速度调节。
实验中我们应用 L298N 芯片实现了高、中、低三档变速,其占空比分别为 100%、75%、50%。
MMa7260 芯片是一种低档加速度 传感器芯片,可以分别测量三个方向 的加速度大小,在零加速度的时候, 输出 1.65V 左右的电压,加速度每增 加 (减小) 一个 g, 输出电压增加 (减 小)800mV,基本成线性变化。
我们 本来想用它,并通过积分的方法实现 对位移的测量,但由于精度不高,加 速度误差大约在 5%左右, 导致实验不
成功。
现在我们改用 MMa 进行小车状态的判断,并使之做到自动调速。
光电对管 的发射极是一个红外线发光二极管,接收级是一个光电三极管, 在无遮挡的时候输出高电平,有遮挡的时候输出低电平。
通过判断输出的下降沿 触发个数计数车轮转过的圈数。
【设计方案】 : 总体来说,该设计要实现两个功能,一是测量功能,二是调速功能。
下面对 这两个功能分别阐述。
1.测量功能的实现 测量距离的基本思路是通过计数车轮转过的圈数 n,然后乘以车轮的周长 C。
由于车轮的周长一般在十厘米左右,为了提高测量的精度,需要对车轮进行必要 的等分。
即在一圈中,系统要计数 N 次, 然后乘以 C/N 得到测量结果。
这样, 测量精度就变成 C/N ,提高了 N 倍。
考虑到测量精度和操作上的诸多因素,我 们对周长进行了三等分,C/ 3=4.134cm。
光电对管安装在被动轮一侧,每一次遮挡将产生一 个电平的下降沿,由 PB0 口读入,产生一次计数。
每两 次计数引发一次中断, 对代表距离的变量自加 0.826867 (以分米为单位) 。
当小车停止后,定时器中断被关闭, 并将距离值送入显示缓冲区并由数码管显示。
一旦小车 继续行驶,定时器中断重新打开,距离又开始累加,等 到下一次停止时再次显示。
我们最初的设计是让数码管即时地显示,但由于显示函数太长、中断太多, 显示亮度不可能很高,示数也很不稳定,影响了读数。
而且即时显示实用性也不 大,所以最终改为让小车停止再后送缓冲区显示。
2.调速功能 (1)H 桥芯片 L298N 的使用 H 桥芯片 L298N 集成了两个 H 桥电路,共有 15 个引脚,应用了其中的 IN1、 IN2、OUT1、OUT2、EnableA、Vcc、Vss 和 GND 八个端口。
Vss 接 6V 电压,IN1、
IN2 分别输入 1、0,代表电机正转,OUT1、OUT2 给电机供电。
使能口 EnableA 输入一个占空比可调的方波,以调节电机的工作电压。
使用 T/C1 定时器产生占空比可调的 PWM 方波,占空比取三个值 100%、50%、 25% , 分 别 对 应 高 速 、 中 速 、 低 速 , 可 以 用 按 键 调 节 档 速 。
(2)MMa7260 集成加速度传感器芯片 另外,我们还应用 Mma 集成传感器芯片,设计了一种可以让小车根据行驶的 状态而自动变速的功能。
使用了 Mma7260 传感器的 Y 轴作为工作轴,固定于平行 于小车行驶的方向。
由于小车行驶的过程中的水平加速度很小,可以忽略。
但是 当小车上坡或下坡的时候,Y 轴向加速度会有较大变化,例如,在 30°斜面上, Y 轴向会附加 0.5g 的加速度,这么大的加速度是可以被测量的。
所以,可以根 据 Y 轴向传感器的输出电压大小来判断上下坡的变化,进而调节电机的转速,使 之适合在不同情况下的行驶状态:上坡时高速,下坡时低速,水平时中速。
(3)按键 利用实验板上的 Key5-8 四个按键, 并时能了 INT0 外部中断, 有按键按下时, 唤醒按键扫描程序。
Key6-8 三个按键分别修改 OCR1L 寄存器的数值,以调节 PWM 的占空比,分别对应低、中、高三档速度,为强制调速按钮。
Key5 按下时,使 能 或 禁 止 ADC 转 换 , 以 进 行 自 动 变 速 , 为 自 由 模 式 切 换 按 钮 。
【程序说明】 1.端口说明
PORTA0~6 数码管段选 PORTA7 ADC 输入 PORTB1 数码管小数点控制 PORTB4~7 按键(上拉) PORTD5 OC1A,PWM 输出 PORTB0 外部 T/C0 引脚(下降沿) PORTD2 INT0 外部中断(上拉)
PORTC 数码管位选
2.主函数部分 主函数主要执行端口和寄存器初始化功能。
void main(void) { CLI(); //disable all interrupts port_init(); timer_init(); //timer interrupt sources timer1_init(); adc_init(); MCUCR&=0xF0; MCUCR|=0x02; //INT0 下降沿 响应中断 GICR&=0x0F; GICR|=0x40; freq=0; shift=0; SEI(); //re-enable interrupts //all peripherals are now 3. T/C0 和 T/C2
label:while(freq<6000); while(1) { TIMSK&= 0x7F; to_disbuffer(); display(); if(freq<5000) { TIMSK|=0x80; goto label; } } }
T/C0 作为计数器,计数光电对管读入的下降沿触发,采用 CTC 模式,不经过 分频,匹配值设为 0x01,即每检测到两次下降沿执行一次 Timer0 比较匹配中断 服务程序,代表距离的变量 shift 加 0.826867,并清零时钟标志 freq。
T/C2 作为计时器,8 分频 CTC 模式,定时周期 0.5ms。
Timer2 比较匹配中断 服务程序中将时钟标志位 freq 加 1。
在主函数中会判断 freq 的值, freq>6000 当 时,表示经过 6000×0.5ms=3s 仍没有增加距离值,此时会执行显示函数,并关 闭 Timer2 中断服务; 此时一旦 Timer0 中断清零 freq, 将重新使能 Timer2 中断, 显示结束。
void timer_init(void) { //T2 初始化 TCCR2=0x0A;//8 分频,ctc 模式 TCNT2=0x00; OCR2=0xF9;//定时周期 0.5ms //T0 初始化 TCCR0=0x0E; TCNT0=0x00; OCR0=0x01; TIMSK=0x82;//使能 T/C0,T/C2 比较匹配 中断 } //T/C0 计时中断服务程序 #pragma interrupt_handler timer0_com_isr:20 void timer0_com_isr(void) { SEI(); time2_new=TCNT2; TCNT2=0x00; TIFR=0x80; freq_temp=freq; freq=0;
freq_temp=freq_temp*250+time2_new; freq_temp=125000/freq_temp; speed=freq_temp*10; shift+=0.8063421144; } //T/C2 计时中断服务程序 #pragma interrupt_handler timer2_com_isr:4 void timer2_com_isr(void) { freq++; if((freq%4==0)&adc_enable=1) //每 2 毫 秒 ADC 转换一次 { ADCSR|=0x40; adc_data=ADCH; adc_in=adc_data*10-1650.000; if(adc_in>400) OCR1AL=0x80; //down else if(adc_in<(-400)) OCR1AL=0x01; //up else OCR1AL=0x40; //flat ADCSR&=0xBF; } }
4.送缓冲区函数 to_disbuffer 和显示函数 display to_disbuffer 函数将 shift 值送与缓冲区, 缓冲区 dis_buff[5]含 5 个元素, 容纳四位有效数字和一个小数点‘p’ 。
如果是大于等于 1 的数,程序自动将第一 个位有效数字付给 dis_buff[4],然后依次存放第二、第三、第四位有效数字或 小数点‘p’ ;如果是小于 1 的数值,将 0 和小数点‘p’分别付给 dis_buff[4] 和 dis_buff[3],然后依次存放小数部分。
显示时,display 函数依次将缓存区中的数值读出,显示范围从 0.000 到 9999,保证了最大的显示精度。
比如,当 shift=0.8063421144 时,显示“0.806” ; 而当 shift=806.3421144 时,则显示“806.3” 。
void to_disbuffer(void) { int i,int_shift; float temp_shift; temp_shift=shift; if(shift<10000&&shift>=1000) { for(i=3;i>=0;i--) { int_shift=temp_shift; dis_buff[4-i]=int_shift%10; int_shift/=10; } dis_buff[0]=’p’; } else if(shift>=100&&shift<1000) { temp_shift*=10; int_shift=(int)temp_shift; for(i=3;i>=0;i--) { dis_buff[4-i]=int_shift%10; int_shift/=10; } dis_buff[0]=dis_buff[1]; dis_buff[1]=’p’; } else if(shift>=10&&shift<100) { temp_shift*=100; int_shift=(int)temp_shift; for(i=3;i>=0;i--) { dis_buff[4-i]=int_shift%10; int_shift/=10; } dis_buff[0]=dis_buff[1]; dis_buff[1]=dis_buff[2];
dis_buff[4]=dis_buff[3]; dis_buff[3]='p'; } else if(shift>=0.1&&shift<1) { temp_shift*=1000; int_shift=(int)temp_shift; for(i=3;i>=0;i--) { dis_buff[3-i]=int_shift%10; int_shift/=10; } dis_buff[3]='p'; dis_buff[4]=0; } else if(shift>=0.01&&shift<0.1) { temp_shift*=1000; int_shift=(int)temp_shift; dis_buff[0]=int_shift%10; int_shift/=10; dis_buff[1]=int_shift%10; dis_buff[4]=0; dis_buff[2]=0; dis_buff[3]='p'; } else for(i=4;i>0;i--) dis_buff[i]=0; } void display(void) // 扫描显示函数 { int i,j,n; for(i=4;i>0;i--) { PORTA=led_7[dis_buff[i]]; PORTC=position[i-1];
dis_buff[2]=’p’; } else if(shift>=1&&shift<10) { temp_shift*=1000; int_shift=(int)temp_shift; for(i=3;i>=0;i--) { dis_buff[3-i]=int_shift%10; int_shift/=10; } 5.ADC 转换
if(dis_buff[i-1]=='p') { PORTB|=0xFD; //PB1 作为小数点输出 for(j=i;j>0;j--) dis_buff[j]=dis_buff[j-1]; } for(n=20;n>0;n--); PORTB&=0x02; PORTC=0x00; } }
传感器 Y 轴输出接 PA7,ADC 采用单次转换模式,内部 2.56V 参考,结果左 对齐。
在 Timer2 中断中,如果已经用按键使能了 ADC 转换,则每隔 2ms 写 1 到 ADCSR 寄存器的 ADSC 位,使能一次单次转换。
由于精度要求不高,只读取高 8 位 ADCH,转换成电压值并执行判断,修改 OCR1 的值达到自动变速的目的。
6. T/C1 的应用,输出 PWM 采用 8 位快速 PWM 方式,WGM[13:0]=5,频率为 60。
仅使能 OC1A 输出,匹配 置位,溢出清零。
改变 OCR1L 的值即可改变占空比。
改变 OCR1 的方式有两种, 一是通过按键,二是通过使能 ADC 转换程序。
//TIMER1 initialize - prescale:8 OCR1AL = 0x82; // WGM: 5) PWM 8bit fast, TOP=OCRnA OCR1BH = 0x00; // desired value: 4KHz OCR1BL = 0xFF; // actual value: 60.000Hz (0.0%) ICR1H = 0x00; void timer1_init(void) ICR1L = 0xFF; { TCCR1A = 0xF1; TCCR1B = 0x00; //stop TCCR1B = 0x0A; //start Timer TCNT1H = 0xFF; //setup TIMSK |= 0x40; TCNT1L = 0x01; } OCR1AH = 0x00; 7.带中断唤醒按键 使能了 INT0 外部中断,下降沿响应中断,作为唤醒键盘扫描程序的条件。
Key6~8 直接改变 OCR1L 的值;Key5 则将 ADCSR 的 ADEN 位和 ADIE 位取反,使能 或禁止 ADC 中断,在 ADC 程序中改变 OCR1L 的值。
//寄存器操作 if((PINB|0x0F)==key_temp)key=key_temp; MCUCR&=0xF0; else key=0xFF; MCUCR|=0x02; //INT0 下降沿 响应 switch(key) 中断 { GICR&=0x0F; case 0x7F : OCR1AL=0x01;break;//key8 up GICR|=0x40; case 0xBF : OCR1AL=0x40;break;//key7 flat case 0xDF : OCR1AL=0x80;break;//key6 #pragma interrupt_handler int0_isr:2 down void int0_isr(void) case 0xEF : ADCSR^=0x88, { adc_enable^=1;
int j; CLI(); key_temp=0xFF; key_temp=PINB|0x0F; for(j=10000;j>=0;j--); 【心得体会】
break;//key5 使能(禁止)ADC,单次转换 default : ; } SEI(); }
在单片机课程中,我们锻炼了团队协作能力和动手实践能力,加深了对 AVR 单片机的学习和认识,熟悉了 ICCavr 编译环境和 AvrStudio4.0 工作平台的使用。
实验中,我们确实遇到很多很的困难。
在硬件的设计方面,由于理论知识的 不足,走了不少的弯路,花费了许多不必要的时间和精力;软件方面,我们补习 了 C 语言的大部分知识, 并参考了他人的一些成功经验, 从最基本的显示函数写 起,经过上百次的调试和修改,逐步形成了最终的程序。
实验中,我们发现,感 觉在理论上认为很简单的事情,在实践的过程中竟然会遇到这么大的困难。
最困 难的不是写程序,而是调试程序。
有时候一段小小的程序就需要修改几十次,这 些困难一直在考验着我们的耐性,只有当静下心来仔细地思考,一个字一个字地 审查,才有可能发现最微小的错误。
所以,在做设计的时候,一定要有耐心,有 恒心,有责任感和克服困难的决心。
经历了这些所有的困难以后,我们终于取得 了成功。
真是与单片机斗,其乐无穷。
课程设计的心得体会
有些事情看着挺简单的,其实只有当我们真正做了才知道到底简单不简单。
很多事情都是表面看起来简单,但真要做起来,就不是那么容易了。
我们的目的是做出东西,为了这我们需要学关于这方面的各种知识,从被动 性的接受知识变成了主动性的寻找知识。
这种模式才是学习的最好方式。
在此制 作过程中我们经历挫折,经历困惑,但有目标在前,我们不能也不想放弃,只有 在克服困难后才会有成功的希望。
我们更学会查找资料因为资料的合理的获取可以帮我们很大的忙。
课程改革的建议。
这门课是培养同学创新能力团队合作能力的一门的课,我们觉得这门课 应有一下改革: 1. 希望实验室能够扩大规模,增加实验设备,增多实验室开放时间。
2
可以加强和工程训练中心的合作,以提高我们项目的含金量。
3. 讲课应该更贴近实际。
贡献值各 1 3 / 【硬件清单】 数码管 LG5641BH 集成 MMa7260 模块 集成 H 桥 L298N 光电对管 1元 3元 45 元 5元
二极管、电容、电路板、电阻及导线若干 【参考文献】
(1)《AVR 单片机嵌入式系统原理与应用实践》 马潮编著 北京航空航天大学出版社 (2)《单片机原理及接口技术实验讲义》 李茂奎著 (3)《C 语言程序设计》 谭浩强编 清华大学出版社 (4)《模拟电路》 童诗白 华成英 主编 高等教育出版社 (5)网站资料
。