学了一年的电脑鼠基本收获不多,也不能说少,至少看了眼界。
挺羡慕之后参见的同学可以有只完好的Micro Mouse,而不用担心电机坏了,红外坏了。
电脑鼠报废主要在红外吧,只能直走,不能避障。庆幸结课时要求不高,能顺利转几圈。
总之,作为软件部分:
快速PWM基本会用;
UART正常;
PID算法,P算法凑数吧;
红外发射接受会写,但硬件不能用;
遗憾;
代码留作纪念;
//ICC-AVR application builder : 2015/11/21 星期六 13:30:53
// Target : M128
// Crystal: 24.0000Mhz
#include <iom128v.h>
#include <macros.h>
#include "uart.h"
#include "motor.h"
unsigned char adc_num;
unsigned char adc_ready;
unsigned char adc_data[7];
unsigned char adc_data_temp[7];
//void delay_ms(int t);
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0xF8;
DDRB = 0xF8;
PORTC = 0x00;
DDRC = 0xFF;
PORTD = 0x00;
DDRD = 0x00;
PORTE = 0x00;
DDRE = 0x00;
PORTF = 0x00;
DDRF = 0x00;
PORTG = 0x00;
DDRG = 0x00;
}
//ADC initialize
// Conversion time: 69uS
void adc_init(void)
{
ADCSRA = 0x00; //disable adc
ADMUX = 0x00; //select adc input 0
ACSR = 0x80;
ADCSRA = 0xCF;
ADMUX = 0x60; //select adc input 0
adc_num=0x00;
adc_ready=0x00;
}
#pragma interrupt_handler adc_isr:iv_ADC
void adc_isr(void)
{
unsigned char tmp;
adc_data_temp[adc_num]=ADCH;
adc_num++;
PORTC=0x01<<adc_num;
ADMUX++;
if(adc_num==0x06 )
{
for( tmp = 0x00; tmp <0x06; tmp++ )
{
// adc_data[tmp]=0x88;
adc_data[tmp]=adc_data_temp[tmp];
}
adc_ready=0x01; // 数据准备OK,申请标志位
adc_num=0x00;
ADMUX &= 0xF8 ;
}
else
ADCSRA|=1<<(ADSC); // 启动ADC 单次循环采样
//conversion complete, read value (int) using...
}
void adc_read(void)
{
ADCSRA|=1<<(ADSC);
}
void adc_put()
{
char k;
Putdata(0xDD);
for(k=0;k<7;k++)
{
Putdata(adc_data[k]);
adc_data[k]=0x00;
}
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
XDIV = 0x00; //xtal divider
XMCRA = 0x00; //external memory
port_init();
timer0_init();
timer1_init();
timer2_init();
timer3_init();
uart1_init();
adc_init();
MCUCR = 0x00;
EICRA = 0x00; //extended ext ints
EICRB = 0x00; //extended ext ints
EIMSK = 0x00;
TIMSK = 0x41; //timer interrupt sources
ETIMSK = 0x04; //extended timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
int i=0,j;
unsigned char v=0;
void main(void)
{
init_devices();
motor_init();
v=0x04;
forward(0x20);
delay_ms(500);
while(1)
{
//这部分应该放在adc转换完成中断里
//由于红外管损坏仅能随便写
while(adc_ready==0x01)
{
adc_ready=0x00;
if(adc_data[3]>=0x20&&adc_data[4]>=0x20)
{
if(adc_data[3]>=0x35)
turn_left(v);
else
turn_right(v);
}
else
forward(v);
// adc_put();
}
adc_read();
delay_ms(10);
}
//insert your functional code here...
}
//motor.h
// 最大速度0x1A; 采样周期越小速度越快,
unsigned char Lcon,Rcon,Lspeed,Rspeed;
int Lptmp,Ltmp,Rptmp,Rtmp;
void motor_message(void)
{
Putdata(0xFF);
Putdata(Lcon);
Putdata(Lspeed);
Putdata(OCR1AL);
Putdata(0xAA);
Putdata(Rcon);
Putdata(Rspeed);
Putdata(OCR1BL);
}
void pid_left(void)
{
Lcon=TCNT2;
TCNT2=0;
Ltmp=(Lspeed-Lcon);
Lptmp+=Ltmp;
if(Lptmp<0) Lptmp=0x00;
if(Lptmp>0xFF) Lptmp=0xFF;
OCR1AL=Lptmp;
}
void motor_left(unsigned char v)
{
Lspeed=v;
}
void pid_right(void)
{
Rcon=TCNT3L;
TCNT3L=0;
Rtmp=(Rspeed-Rcon)*8;
Rptmp+=Rtmp;
if(Rptmp<0x00) Rptmp=0x00;
if(Rptmp>0xFF) Rptmp=0xFF;
OCR1BL=Rptmp;
}
void motor_right(unsigned char v)
{
Rspeed=v;
// Putdata(0x2B);
}
void turn_left(unsigned char v)
{
motor_right(0x1A);
motor_left(v);
delay_ms(10);
motor_right(v);
}
void turn_right(unsigned char v)
{
motor_left(0x1A);
motor_right(v);
delay_ms(10);
motor_right(v);
}
void forward(unsigned char v)
{
motor_left(v);
motor_right(v);
}
//TIMER0 initialize - prescale:8
// WGM: PWM Fast
// desired value: 1Hz
// actual value: 11718.750Hz (100.0%)
void timer0_init(void)
{
TCCR0 = 0x00; //stop
ASSR = 0x00; //set async mode
TCNT0 = 0x01; //set count
OCR0 = 0xFF;
TCCR0 = 0x6A; //start timer
}
unsigned int count=0,temp1=0;
unsigned char temp2;
#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
void timer0_ovf_isr(void)
{
//reload counter value
count++;
if(count>=8)
{
temp1++;
if(temp1>=150)
{
// Putdata(0xBB);
// Putdata(0xBB);
// Putdata(0xBB);
// motor_message();
adc_put();
temp1=0;
}
// delay_ms(500);
// Putdata(0xF0);
// Putdata(TCNT3L);
pid_right();
pid_left();
count=0;
// motor_message();
}
TCNT0 = 0x01;
}
//TIMER1 initialize - prescale:8
// WGM: 5) PWM 8bit fast, TOP=0x00FF
// desired value: 1Hz
// actual value: 11718.750Hz (100.0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0xFF; //setup
TCNT1L = 0x01;
OCR1AH = 0x00;
OCR1AL = 0xFF;
OCR1BH = 0x00;
OCR1BL = 0xFF;
OCR1CH = 0x00;
OCR1CL = 0xFF;
ICR1H = 0x00;
ICR1L = 0xFF;
TCCR1A = 0xA9;
TCCR1B = 0x0A; //start Timer
}
//TIMER2 initialize - prescale:Stop
// WGM: Normal
// desired value: 1Hz
// actual value: Out of range
void timer2_init(void)
{
TCCR2 = 0x00; //stop
TCNT2 = 0x00 /*INVALID SETTING*/; //setup
OCR2 = 0x00 /*INVALID SETTING*/;
TCCR2 = 0x07; //start
}
#pragma interrupt_handler timer2_ovf_isr:iv_TIM2_OVF
void timer2_ovf_isr(void)
{
TCNT2 = 0x00 /*INVALID SETTING*/; //reload counter value
}
//TIMER3 initialize - prescale:Stop
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 1Hz
// actual value: Out of range
void timer3_init(void)
{
TCCR3B = 0x00; //stop
TCNT3H = 0x00 /*INVALID SETTING*/; //setup
TCNT3L = 0x00 /*INVALID SETTING*/;
OCR3AH = 0x00 /*INVALID SETTING*/;
OCR3AL = 0x00 /*INVALID SETTING*/;
OCR3BH = 0x00 /*INVALID SETTING*/;
OCR3BL = 0x00 /*INVALID SETTING*/;
OCR3CH = 0x00 /*INVALID SETTING*/;
OCR3CL = 0x00 /*INVALID SETTING*/;
ICR3H = 0x00 /*INVALID SETTING*/;
ICR3L = 0x00 /*INVALID SETTING*/;
TCCR3A = 0x00;
TCCR3B = 0x07; //start Timer
}
#pragma interrupt_handler timer3_ovf_isr:iv_TIM3_OVF
void timer3_ovf_isr(void)
{
//TIMER3 has overflowed
TCNT3H = 0x00 /*INVALID SETTING*/; //reload counter high value
TCNT3L = 0x00 /*INVALID SETTING*/; //reload counter low value
Putdata(0x33);
}
void motor_init(void)
{
OCR1A=0x00;
OCR1B=0x00;
OCR1C=0x00;
OCR0=0x00;
Lcon=0x00;
Lspeed=0x00;
Lptmp=0x00;
Ltmp=0x00;
Rcon=0x00;
Rspeed=0x00;
Rptmp=0x00;
Rtmp=0x00;
}
//uart.h
void delay_us(int t)
{ int i;
while(t--);
for(i=0;i<34;i++);
}
void delay_ms(int t) //延迟ms
{
int i,j;
for(i=0;i<t;i++)
for(j=0;j<3400;j++);
}
//UART1 initialize
// desired baud rate:115200
// actual baud rate:115385 (0.2%)
// char size: 8 bit
// parity: Disabled
void uart1_init(void)
{
UCSR1B = 0x00; //disable while setting baud rate
UCSR1A = 0x00;
UCSR1C = 0x06; //设置传输位数8位
UBRR1L = 0x0C; //set baud rate lo
UBRR1H = 0x00; //set baud rate hi
UCSR1B = 0x98; //发送使能\接收中断使能\接受使能
}
void Putdata(unsigned char g_Dat) // 串口写函数 g_Dat:往串口写的数据
{
while (!(UCSR1A & (BIT(UDRE1)))); // 等待传送结束 等待发送缓冲区空
UDR1 = g_Dat;
}
unsigned char get_data[7],shou;
unsigned char data_ready,data_count=0;
#pragma interrupt_handler uart1_rx_isr:iv_USART1_RXC
void uart1_rx_isr(void)
{
get_data[data_count++]=UDR1;
// motor_left(get_data[data_count-1]);
if(data_count>=1)
{
data_ready=1;
data_count=0;
// Putdata(0x2B);
}
//uart has received a character in UDR
}
以下图片版权归邱哥所有,请勿擅自使用!