原创 竞赛结束,,

2007-9-7 21:42 3095 12 15 分类: 工程师职场

竞赛结束了,,成果不太理想,,跷跷板小车。。能够实现基本功能,,但我的小车最后又出了问题,,后退的时候程序老跑飞。。用的是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:时间是漂流的河,,生命是一叶舟,,你是撑篙人,,要么激流勇进,,要么随波逐流。。

文章评论3条评论)

登录后参与讨论

用户377235 2014-1-20 20:47

project- propeties- c/c general-paths and symbols

用户1485066 2011-5-20 09:11

我用的NIos9.1,但是NIos编译找不到自身文件altera_avalon_uart_regs,而这个软件里面,我找到了这个文件,我现在想知道怎么让NIos自动找到我添加的系统文件,避免报错

用户1532875 2007-10-27 15:52

不是吧,这么简单2505

 

yoyowind 2007-10-16 10:40

我们这三个小孩用凌阳做的,给他们讲了讲思路拿了全国一等奖,还不错。

用户75640 2007-9-9 11:43

我们也是用AVR来做的哦!!

相关推荐阅读
用户85913 2010-10-16 13:47
手机软件
...
用户85913 2008-03-15 17:28
LCD--HDM32GS12-B仿真==新进展
搞了这N多天了,,有些进展,,贴出来,,留纪念。。后面有仿真的包和Keil的包,,玩这块液晶的可以看下,,另外请高手指点下怎么设置列位置,,一直设置不了。。...
用户85913 2008-03-08 16:01
Proteus中液晶模块中文资料
最近两天一直在弄Proteus的液晶,,网上找到的一点东西,,发这里来,,大家看看。。还有一本关于液晶的书( PDF)讲得n详细,,从LCD原理一直到使用方法都有,,要的下了看。。下了之后从左到右依次...
用户85913 2008-03-07 12:39
Proteus-----1602液晶显示
论坛里有人问Proteus液晶显示的问题,,就下来弄了弄,,搞不定。。Proteus基础不行,,对它的LCD不太了解,,所以弄了这个1602的先熟悉下,,等下再弄汉显的。。包里面有Keil和Prote...
用户85913 2008-02-18 22:31
年假回来
    哦,,回来了。。    年假看了点三级的书和arm的书,,两本都没看完,,凑过年算了下欠下的东西和要学的东西,,这个学期的::    先说欠下的,,电基及模数电各复习一遍,,说是复习其实和学习...
用户85913 2008-01-04 22:43
新的一年总该有点寄语。。
    元旦几天了,,老想着写点东西,,但有考虑没什么好写,,就一直推到了现在。。    07送走了,,有什么感觉呢??应该算平淡的一年吧。。没有什么特别的。。喜欢过一个女孩,,去了一趟上海,,参加了...
我要评论
3
12
关闭 站长推荐上一条 /2 下一条