竞赛结束了,,成果不太理想,,跷跷板小车。。能够实现基本功能,,但我的小车最后又出了问题,,后退的时候程序老跑飞。。用的是avr mega8515l,,把片放到另一个小车上,,完全正常。。搞不懂怎么回事~~
把程序贴出来,,各部分功能都是正常的,,供大家参考,,不对的的地方希望指正。。
PCB是我的搭档搞的,,等下发出来。。
#include
#include
#define lcd_data_port PORTA
#define lcd_data_ddr DDRA
#define lcd_busy_pin PINA
#define lcd_busy_ddr DDRA
#define lcd_control_port PORTC
#define lcd_control_ddr DDRC
#define lcd_RS 0x01
//PORTC0
#define lcd_RW 0x02
//PORTC1
#define lcd_EN 0x04
//PORTC2
#define busy 0x80
//LCD_DB7
/*----------------------------------函数声明----------------------------------*/
//IO口相关
void io_init(void);
//LCD相关
void lcd_init(void);
void lcd_write_command(unsigned char command,unsigned char wait_en);
void lcd_write_data(unsigned char char_data);
void wait_enable(void);
void display_a_char(unsigned char position,unsigned char char_data);
void display_a_string(unsigned char position,unsigned char *ptr);
void display_a_number(unsigned char position,int i);
int ntentimes(unsigned char n);
//键盘相关
void scankeyonce(void);
unsigned char key_scanonce(void);
int scannum(void);
unsigned char bitchg(unsigned char bit);
unsigned int numchg(unsigned int num,int i);
//直流电机相关
void wgm_init(void);
void motorl(int spdl);
void motorr(int spdr);
void motor(unsigned char x,int spd);
void stop(void);
void goline(int speed,unsigned int time);
//时间相关
void delay_ns(unsigned int n);
void delay_nms(unsigned int n);
void delay_1ms(void);
void delay_nus(int n);
//中断相关
void time_init(void);
void Timer0(void);
//警报相关
void alarmstart(void);
void alarmstop(void);
//全局变量
void main1(void);
void main2(void);
void main3(void);
void main4(void);
unsigned char str0[]="Input the car speed ";
unsigned char str1[]="Input the time(ms) !";
unsigned char str2[]="00:00:00";
unsigned char str3[]=" ";
unsigned char str4[]="B to A:";
unsigned char str5[]=" Choose the program ";
unsigned char str6[]=" Input back times ! ";
unsigned char str7[]="A to B:";
unsigned char keycode,keyflag=0,num=0,minute=0,second=0;
/*------------------------------------主函数----------------------------------*/
void main(void)
{
unsigned int i;
io_init();
lcd_init();
wgm_init();
time_init();
while(1)
{
lcd_init();
display_a_string(0,str5);
i="scannum"();
switch(i)
{
case 1:lcd_init();display_a_string(20,str3);main1();break;
case 2:lcd_init();display_a_string(20,str3);main2();break;
case 3:lcd_init();display_a_string(20,str3);main3();break;
case 4:lcd_init();display_a_string(20,str3);main4();break;
}
}
}
/*------------------------------------ 程序一 --------------------------------*/
void main1(void)
{int speed;
unsigned char minute0,second0,minute1,second1,minute2,second2;
display_a_string(0,str0);
speed=scannum();
delay_ns(1);
minute0=minute;
second0=second;
goline(speed,1);
second1=second-second0;
minute1=minute-minute0;
motor(1,-35);
motor(2,-35);
display_a_string(40,str7);
display_a_char(47,'0');
display_a_number(48,minute1);
display_a_char(49,':');
if(second1<10)
{display_a_char(50,'0');
display_a_number(51,second1);}
else display_a_number(52,second1);
delay_ns(5);
minute0=minute;
second0=second;
goline(speed*(-1),1);
motor(1,35);
motor(2,35);
second2=second-second0;
minute2=minute-minute0;
display_a_string(60,str4);
display_a_char(67,'0');
display_a_number(68,minute2);
display_a_char(69,':');
if(second2<10)
{display_a_char(70,'0');
display_a_number(71,second2);}
else display_a_number(70,second2);
delay_ns(5);
stop();
delay_ns(15);
stop();
}
/*----------------------------------- 程序二 --------------------------------*/
void main2(void)
{
unsigned char i="0",topflag=0x00;
int lspeed="0";
PORTD|=0x01;//平衡杆信号输入口
DDRD&=0xfe;
display_a_string(0,str0);
lspeed="scannum"();
goline(100,5000);
topflag="0x01"&PIND;
alarmstart();
while(1)
{
topflag="0x01"&PIND;
if(topflag==0x01)//前进
{goline(lspeed,130);delay_nms(1500);}
else if(topflag==0x00)//后退
{goline(lspeed*(-1),150);delay_nms(1500);}
else stop();
}
alarmstop();
display_a_char(50,i+0x30);
delay_ns(20);
stop();
}
/*------------------------------------ 程序三 --------------------------------*/
void main3(void)
{
unsigned char i;
int speed3;
display_a_string(0,str0);
speed3=scannum();
lcd_init();
display_a_string(0,str6);
i=scannum();
delay_ns(1);
goline(95,1);
motor(1,-35);
motor(2,-35);
delay_ns(3);
for(;i>0;i--)
{
goline(speed3*(-1),60);
delay_ns(1);
}
alarmstart();
delay_ns(10);
alarmstop();
}
/*------------------------------------ 程序四 --------------------------------*/
void main4(void)
{int speed;
display_a_string(0,str0);
speed="scannum"();
delay_ns(1);
goline(speed,1);
alarmstart();
delay_ns(10);
alarmstop();
}
/*-----------------------------------测试程序---------------------------------*/
//void test(void)
//{
// ;
// }
/*---------------------------------直流电机函数-------------------------------*/
void wgm_init(void)
{TCCR1A=0xa3;
TCCR1B=0x02;
DDRD|=0x20;
DDRE|=0x04;
}
void motor(unsigned char x,int spd)
{
if(x==1)
{if(spd>=0)
{DDRD|=0x40;PORTD&=0xbf;}
else
{DDRD|=0x40;PORTD|=0x40;spd=-spd;}
spd="10"*spd+23*spd/100;
OCR1AH=spd>>8;
OCR1AL=0x00ff&spd;}
if(x==2)
{if(spd>=0)
{DDRD|=0x80;PORTD&=0x7f;}
else
{DDRD|=0x80;PORTD|=0x80;spd=-spd;}
spd="10"*spd+23*spd/100;
OCR1BH=spd>>8;
OCR1BL=0x00ff&spd;}
}
void stop(void)
{motor(1,0);
motor(2,0);}
void goline(int speed,unsigned int time)
{
unsigned char bottomflag,i=0;
if(speed>=0)
{PORTC|=0xf8;DDRC&=0x07;bottomflag=0xf8&PINC;}
else
{PORTB|=0xf8;DDRB&=0x07;bottomflag=0xf8&PINB;}
bottomflag="0x20";
for(;time>0;time-=10)
{if(time==1)time+=10;
switch(bottomflag)
{
case 0x80:motor(1,speed/5);motor(2,speed);delay_nms(10);break;//10000
case 0xc0:motor(1,speed/5);motor(2,speed);delay_nms(10);break;//11000
case 0x40:motor(1,speed/5);motor(2,speed);delay_nms(10);break;//01000
case 0x60:motor(1,speed/4);motor(2,speed);delay_nms(10);break;//01100
case 0x20:motor(1,speed);motor(2,speed);delay_nms(10);break;//00100
case 0x30:motor(1,speed);motor(2,speed/4);delay_nms(10);break;//00110
case 0x10:motor(1,speed);motor(2,speed/5);delay_nms(10);break;//00010
case 0x18:motor(1,speed);motor(2,speed/5);delay_nms(10);break;//00011
case 0x08:motor(1,speed);motor(2,speed/5);delay_nms(10);break;//00001
default:break;
}
if(speed>=0)
{PORTC|=0xf8;DDRC&=0x07;bottomflag=0xf8&PINC;}
else
{PORTB|=0xf8;DDRB&=0x07;bottomflag=0xf8&PINB;}
if(bottomflag==0x00)
{if(i<=8)
{motor(1,speed);motor(2,speed);delay_nms(10);i++;}
else break;
}
}
stop();
}
/*-----------------------------------声控函数---------------------------------*/
void mic(void)
{
DDRE&=0xfd;
PORTE|=0x02;
while((PINC&0x04)==0);}
/*-----------------------------------报警函数---------------------------------*/
void alarmstart(void)
{
DDRD|=0x02;
PORTD|=0x02;
}
void alarmstop(void)
{
DDRD|=0x02;
PORTD&=0xfd;
}
/*-----------------------------------键盘函数---------------------------------*/
void scankeyonce(void)//按键扫描一次函数
{ unsigned char i;
for(i=1;i<9;i*=2)
{DDRA=i;
PORTA=~i; //if(i==8)i=1;
NOP();
keycode=~PINA;
if(keycode!=i)
{delay_nms(30);
keycode=~PINA;
if(keycode!=i)
{
keycode=(bitchg((0x0f&i)))*4+bitchg(((0xf0&keycode)>>4));
while((0xf0&PINA)!=0xf0);
break;
}
}
keycode="0xff";
}
}
unsigned char key_scanonce(void)
{
unsigned char i;
for(i=1;i<9;i*=2)
{DDRA=i;
PORTA=~i; //if(i==8)i=1;
NOP();
keycode=~PINA;
if(keycode!=i)
{delay_nms(30);
keycode=~PINA;
if(keycode!=i)
{
keycode=(bitchg((0x0f&i)))*4+bitchg(((0xf0&keycode)>>4));
while((0xf0&PINA)!=0xf0);
break;
}
}
keycode="0xff";
}
switch(keycode)
{
case 0x00:return '1';
case 0x01:return '2';
case 0x02:return '3';
case 0x03:return 'a';
case 0x04:return '4';
case 0x05:return '5';
case 0x06:return '6';
case 0x07:return 'b';
case 0x08:return '7';
case 0x09:return '8';
case 0x0a:return '9';
case 0x0b:return 'c';
case 0x0c:return '*';
case 0x0d:return '0';
case 0x0e:return '#';
case 0x0f:return 'd';
case 0xff:return 0xff;
default:return 0xff;
}
}
unsigned char bitchg(unsigned char bit)//四位bit码翻译成行列位置
{if(bit&0x01) bit="0";
else if(bit&0x02) bit="1";
else if(bit&0x04) bit="2";
else bit="3";
return(bit);
}
int scannum(void)//键盘输入一整型数据
{
unsigned char strnum[6];
unsigned char i;
int keynum="0";
keyflag="1";
for(i=6;i>=0;i--)
{do{keycode=key_scanonce();}while(keycode==0xff);//一直扫描键盘,,直到有按键按下
if(keycode!='d')//是否回车(d号键) ?否 !
{if(keycode=='c')//是否清除(c号键) ?是 !
{delay_nms(10);display_a_char((25-i),' ');i+=2;}
else//是否清除(c号键) ?否 !
{if(keycode=='b')//是否负号(b号键) ?是 !
{delay_nms(10);display_a_char((25-i),'-');strnum[6-i]=keycode-0x30;}
else//是否负号(c号键) ?否 !
{delay_nms(10);display_a_char((26-i),keycode);strnum[6-i]=keycode-0x30;}
}
}
else//是否回车(d号键) ?是 !
{delay_nms(10);display_a_char((26-i),0x7f);
if(strnum[0]=='b')//负数的运算
{switch(i)
{case 5:keynum=0;break;
case 4:keynum=(-1)*(strnum[1]);break;
case 3:keynum=(-1)*(strnum[1]*10+strnum[2]);break;
case 2:keynum=(-1)*(strnum[1]*100+strnum[2]*10+strnum[3]);break;
case 1:keynum=(-1)*(strnum[1]*1000+strnum[2]*100+strnum[3]*10+strnum[4]);break;
case 0:keynum=(-1)*(strnum[1]*10000+strnum[2]*1000+strnum[3]*100+strnum[4]*10+strnum[5]);break;//|keynum|应小于32767
}
}
else //正数的运算
{switch(i)
{case 6:keynum=0;break;
case 5:keynum=strnum[0];break;
case 4:keynum=strnum[0]*10+strnum[1];break;
case 3:keynum=strnum[0]*100+strnum[1]*10+strnum[2];break;
case 2:keynum=strnum[0]*1000+strnum[1]*100+strnum[2]*10+strnum[3];break;
case 1:keynum=strnum[0]*10000+strnum[1]*1000+strnum[2]*100+strnum[3]*10+strnum[4];break;//keynum应小于32767
}
}
break;//跳出for循环
}
}
keyflag=0;
return(keynum);
}
unsigned int numchg
(unsigned int num,int i)
{
if(i>0)
{for(;i>0;i--)
{num=num*10;}
}
else
{for(;i<0;i++)
{num=num/10;}
}
return(num);
}
/*------------------------------------液晶驱动函数----------------------------*/
//液晶初始化
void lcd_init(void)
{
delay_nms(30);
lcd_data_port=0xff;
lcd_data_ddr=0xff;
lcd_control_port=0x00;
lcd_control_ddr=0x07;
lcd_write_command(0x38,0);//显示模式设置三次(此时不管lcd空闲与否)
delay_nms(1);
lcd_write_command(0x38,0);
delay_nms(1);
lcd_write_command(0x38,0);
delay_nms(1);
lcd_write_command(0x38,1);//显示模式设置(从此之后均需lcd空闲)
lcd_write_command(0x08,1);//显示关闭
lcd_write_command(0x01,1);//显示清屏
lcd_write_command(0x06,1);//显示光标移动设置
lcd_write_command(0x0c,1);//显示开及光标设置
delay_nus(30);
lcd_write_command(0x01,1);//显示清屏
}
//写指令函数: E="高脉冲" RS="0" RW="0//command为指令",wait_en指定是否要检测LCD忙信号
void lcd_write_command(unsigned char command,unsigned char wait_en)
{
if(wait_en)wait_enable();//若wait_en为1,则要检测LCD忙信号,等待其空闲
lcd_control_port&=~lcd_RS;//RS=0
lcd_control_port&=~lcd_RW;//RW=0
lcd_control_port&=~lcd_EN;//E=0,下面给LCD一个高脉冲
lcd_data_ddr=0xff;
lcd_data_port=command;
lcd_control_port|=lcd_EN;//E=1
lcd_data_port=command;
lcd_control_port&=~lcd_EN;//重设E=0
}
//写数据函数: E =高脉冲 RS="1" RW="0"
void lcd_write_data(unsigned char char_data)
{
wait_enable();//等待LCD空闲
lcd_control_port|=lcd_RS;//RS=1数据
lcd_control_port&=~lcd_RW;//RW=0写
lcd_control_port&=~lcd_EN;//E=0,下面给LCD一个高脉冲
lcd_data_ddr=0xff;
lcd_data_port=char_data;
lcd_control_port|=lcd_EN;//E=1
lcd_data_port=char_data;
lcd_control_port&=~lcd_EN;//重设E=0
}
//正常读写操作之前必须检测LCD控制器状态:E=1 RS="0" RW="1";DB7: 0 空闲,1 忙。
//检测忙信号,等待LCD空闲函数
void wait_enable(void)
{
lcd_busy_ddr&=~busy;//设置busy口为输入
lcd_control_port&=~lcd_RS;//RS=0
lcd_control_port|=lcd_RW;//RW=1
lcd_control_port&=~lcd_EN;//E=0,下面给LCD一个高脉冲
NOP();
lcd_control_port|=lcd_EN;//E=1
while(lcd_busy_pin&busy);//等待LCD_DB7为0
lcd_control_port&=~lcd_EN;//重设E=0
lcd_busy_ddr|=busy;//设置busy口为输出
}
void display_a_char(unsigned char position,unsigned char char_data)//参数position指定位置0~79,char_data为要显示的字符
{
unsigned char position_tem;
if(position<20) //第一行时,地址为0x80到0x93,输入的数值加上0x80, 就是当前的地址值;
position_tem=position+0x80;
else if(position<40)//第二行的地址为0xc0到0xd3,当为第二行时position>20,此时地址值应为position+0xc0-0x20即position+0xac;
position_tem=position+0xac;
else if(position<60)//第三行的地址为0x94到0xa7,当为第三行时position>40,此时地址值应为position+0x94-0x40即position+0x6c;
position_tem=position+0x6c;
else//第四行的地址为0xd4到0xe7,当为第三行时position>60,此时地址值应为position+0xd4-0x60即position+0x98;
position_tem=position+0x98;
lcd_write_command(position_tem,1);
lcd_write_data(char_data);
}
//指定位置显示任意大小字符串
void display_a_string(unsigned char position,unsigned char *ptr)
{
unsigned char position_tem,i=0,i_tem=0;
lcd_data_port=0xff;
lcd_data_ddr=0xff;
lcd_control_port=0x07;
lcd_control_ddr=0x07;
for(i=0;*(ptr+i)!=0;i++)
i_tem++;
position_tem=position;
for(i=0;i display_a_char(position_tem++,*(ptr+i));
}
//指定位置显示一个整数
void display_a_number(unsigned char position,int num)
{
int j;
unsigned char i,x;
if(num>=10000)i=5;
else if(num<10000&&num>=1000)i=4;
else if(num<1000&&num>=100)i=3;
else if(num<100&&num>=10)i=2;
else if(num<10&&num>=0)i=1;
else if(num<=-10000)i=15;
else if(num>-10000&&num<=-1000)i=14;
else if(num>-1000&&num<=-100)i=13;
else if(num>-100&&num<=-10)i=12;
else i="11";
if(i<10)
{for(;i>0;i--)
{
j="ntentimes"(i-1);
x="num/j";
display_a_char(position,x+0x30);
num="num"%j;
position++;
}
}
else
{
i-=10;
display_a_char(position,'-');
position++;
for(;i>0;i--)
{
j="ntentimes"(i);
x="num/j";
display_a_char(position,x+0x30);
num="num"%j;
position++;
}
}
}
//n的10次方转换
int ntentimes(unsigned char n)
{int m="1";
for(;n>0;n--)
{m*=10;}
return(m);
}
/*------------------------------------计时函数--------------------------------*/
void time_init(void)
{
SREG="0x80";
TIMSK="0x02";
TCCR0=0x04; //T/C0工作于定时方式,系统时钟256分频
TCNT0=0x06; //计数初始值6
}
/*------------------------------------延时函数--------------------------------*/
void delay_ns(unsigned int n)
{
unsigned int i,j;
for(i=0;i {for(j=1000;j>0;j--)
delay_1ms();
}
}
//n ms延时函数
void delay_nms(unsigned int n)
{
unsigned int i;
n-=n/1000;
for(;n!=0;n--){for(i=1328;i!=0;i--) ; }
}
//1ms延时函数
void delay_1ms(void)
{
unsigned int i;
for(i=1328;i!=0;i--);
}
//n us延时函数
void delay_nus(int n)
{while(n--);}
/*-----------------------------------端口初始化-------------------------------*/
void io_init(void)
{DDRA=0xff;
PORTA="0x00";
DDRB="0x00";
PORTB="0xff";
DDRC="0x07";
PORTC="0x07";
DDRD="0xff";
PORTD="0xf0";
DDRE="0x07";
PORTE="0x00";
}
/*------------------------------T/C0中断服务函数------------------------------*/
#pragma interrupt_handler Timer0:8
void Timer0(void)
{
num++; //中断次数累加
if(num==122)
{
num="0"; //计数到125次,计数值复位
second++; //秒加1
if(second==60)
{second=0;
minute++;} //分进位
if(keyflag==0)
{if(minute<10){display_a_char(75,'0');display_a_number(76,minute);}
else display_a_number(75,minute);
display_a_char(77,':');
if(second<10){display_a_char(78,'0');display_a_number(79,second);}
else display_a_number(78,second);
}
}
}
PS:时间是漂流的河,,生命是一叶舟,,你是撑篙人,,要么激流勇进,,要么随波逐流。。
用户377235 2014-1-20 20:47
用户1485066 2011-5-20 09:11
用户1532875 2007-10-27 15:52
不是吧,这么简单2505
yoyowind 2007-10-16 10:40
用户75640 2007-9-9 11:43
我们也是用AVR来做的哦!!