⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 new_wuxian.c

📁 AVR单片机组成的智能小车的无线驱动程序
💻 C
字号:
/************************************************************
      芯片:ATEML MEGA168
	  程序:小车与无线模块之间的通信程序 V2.0 Beta
	  无线模块:nfr401
	  日期:2007.07.15
	  版本号:20070715
	  源程序:双龙公司提供
	  Mail:digispy@163.com
	  升级信息:在原来程序的基础上增加了走弧线、走矩形、走8字
	  躲避悬前方障碍等功能,还可以在此基础上用基本的前后左右组
	  合新的行走路线
---------------------------------------------------------------  
      无线模块的接口   功能         MEGA168的引脚
            PIN1       TXEN           PB2
            PIN2       PWR_UP         PB0
     	    PIN3       GND
			PIN4       CS             PB1
			PIN5       GND
			PIN6       DIN            PD1   TXD
			PIN7       GND
			PIN8       DOUT           PD0   RXD
			PIN9       GND            
			PIN10      VCC
---------------------------------------------------------------					              
       无线模块的引脚功能
	    TXEN        0:Receive        1:transmit    default: 0
		PWR_UP      0:standby        1:operate     default: 1
		CS          0: 433.93MHz     1:434.33MHz   default: 1
		DIN         data input
		DOUT        data output			
--------------------------------------------------------------
        小车的驱动马达引脚
		左边的驱动马达             MEAG168引脚
                  IA               PD4
                  IB               PD5
		右边的驱动马达             MEAG168引脚
		          IA               PD6
				  IB	    	   PD7
--------------------------------------------------------------
小车驱动控制指令
小车向前
         PD4=0  PD5=1  //左马达
		 PD6=0  PD7=1  //右马达
		 PD|=0xF0;
		 PD&=0x5F;
小车向后
         PD4=1  PD5=0  //左马达
		 PD6=1  PD7=0  //右马达
		 PD|=0xF0;
		 PD&=0XAF;  
小车向左
         PD4=1  PD5=0  //左马达
		 PD6=0  PD7=1  //右马达
		 PD|=0xF0;
		 PD&=0X9F;
小车向右
         PD4=0  PD5=1  //左马达
		 PD6=1  PD7=0  //右马达
		 PD|=0xF0;
		 PD&=0X6F;
小车停止			   	
         PD4=0  PD5=0  //左马达
		 PD6=0  PD7=0  //右马达
		 PD&=0x0F;  
--------------------------------------------------------------	
通信协议
 (1) 每次发送数据为10个字节
 (2) 第一个字节以0x24开头 
 (3) 第二个字节为小车号码
 (4) 第三至九个字节为数据
 (5) 第十个字节为0x2A结束
 (6) 每个小车都有一个唯一的地址写在EEPROM的每一个字节中
目前用到的指令(数据部分)
  前四个字节是命令,后三个字节是数据
  0xFF 0xFF 0xFF 0XFF     0X00 0X00 0X00  
     
*************************************************************/
#include	"iom168v.h"
#include     <iom48v.h>
#include     <macros.h>
void Stop(void);
/************************************************************
                    声明全局变量
************************************************************/
#define fosc 		7372800
#define baud    	9600    
#define CAR_NUM     0x31   //这个值每个小车只能有一个
#define ALL_CAR_NUM 0x00   //这个值是全部小车要有同一个动作

#pragma interrupt_handler uart0_rx_isr:19  
#pragma interrupt_handler uart0_tx_isr:20
unsigned char mid;
unsigned char Rx_Buf[11];  //接收缓冲区
unsigned char rCount=0;
unsigned char Flag_StartRec=0;
unsigned char check_table[17]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};


/*************************************************************
                 无线模块初始化函数
*************************************************************/
void Nfr401_Init()
{
   DDRB|=0x07;    // 0000 0111  设置B口后三位为输出端口   
   PORTB&=0xFB;   // PB2=0;  1111 1011 为接收状态
   PORTB|=0x03;   // PB1=1; PB0=1;  0000 0011
}
/*************************************************************
                 小车初始化函数
*************************************************************/
void Car_Init()
{
 DDRD=0XF0;//设置PB输出
 PORTD = 0XF0;//设置pc0输入?
 
}
/*************************************************************
                 延迟函数
*************************************************************/
void Delay()
{ 
  unsigned int i;
  for(i=0;i<=10000;i++);
}
/*************************************************************
                 小车向前函数
*************************************************************/
void Go_Ahead(unsigned int t)
{
 unsigned int i;
 PORTD=0XA0;//向前1010 0000
 for(i=0;i<=t;i++)
    {
      Delay();
    }
 Stop(); 	 
}
/*************************************************************
                 小车向后函数
*************************************************************/
void Go_Back(unsigned int t)
{ 
  unsigned int i;
  PORTD=0X50;//向后 0101 0000
  for(i=0;i<=t;i++)
    {
      Delay();
    }
  Stop();
}
/*************************************************************
                 小车向左函数
*************************************************************/
void Turn_Left(unsigned int t)
{
  unsigned int i;
  PORTD=0x80;//左转 pd7=0,pd6=1,pd5=0,pd4=0 1000 0000
  for(i=0;i<=t;i++)
    {
      Delay();
    }
  Stop();
}
/*************************************************************
                 小车向右函数
*************************************************************/
void Turn_Right(unsigned int t)
{ 
  unsigned int i;
  PORTD=0x20;//右转 0010 0000
   for(i=0;i<=t;i++)
    {
      Delay();
    }
  Stop();
}
/*************************************************************
                 小车停止函数
*************************************************************/
void Stop()
{
  PORTD=0x00; //0000 0000
}
/*************************************************************
                 小车走弧线
*************************************************************/
void  Circle(unsigned int t)
{
  unsigned int i;
  for(i=0;i<=t;i++)
    {
      Go_Ahead(4);
	  Turn_Right(1);
    }
}
/*************************************************************
                 小车走8字
*************************************************************/
void  Eight_R(unsigned int t) //右转圈
{
  unsigned int i;
  for(i=0;i<=t;i++)
    {
      Go_Ahead(1);
	  Turn_Right(5);
    }
}
void  Eight_L(unsigned int t) //左转圈
{
  unsigned int i;
  for(i=0;i<=t;i++)
    {
      Go_Ahead(1);
	  Turn_Left(5);
    }
}
/*void Eight(unsigned int t) //t设置为走8字的次数
{
  unsigned int i;
  for(i=0;i<=t;i++)
  {
     Eight_R(60);
     Eight_L(60);
  }	 
}*/
/*************************************************************
                 小车躲避前方障碍
*************************************************************/
void timer0_init(void)//定时器初始化
{
 TCCR0B = 0x00; 
 TCNT0 = 0x00; 
 TCCR0A = 0x00;
 TCCR0B = 0x03;  //32分频
}
void PortInit(void)//C、D口初始化
{
DDRD=0XF0;
DDRC=0X00;
PORTC=0XFF;
}

//避障碍主程序
void xuanya(void)
{
unsigned int i;   
PortInit();
timer0_init();
while(1)
 {   
  while((PINC&(1<<PC2))!=0)//当PC2引脚不为"0"时
  {
   Go_Ahead(20);
  } 
  while((PINC&(1<<PC2))==0)//当PC2引脚为"0"时
  {   
     Go_Back(30);
	 Turn_Left(45);
  }
 } 
}
/*************************************************************
                 串口接收后的处理函数
*************************************************************/
void Dispose(void)
{ 
     if(Rx_Buf[1]==CAR_NUM || Rx_Buf[1]==ALL_CAR_NUM)
	   {
	   	  if(Rx_Buf[2]==0x41 && Rx_Buf[3]==0x41 && Rx_Buf[4]==0x41 && Rx_Buf[5]==0x41)
		       {
			    Go_Ahead(100);
			   }
          if(Rx_Buf[2]==0x42 && Rx_Buf[3]==0x42 && Rx_Buf[4]==0x42 && Rx_Buf[5]==0x42)
		       {
			   Go_Back(100); 
			   }
		  if(Rx_Buf[2]==0x43 && Rx_Buf[3]==0x43 && Rx_Buf[4]==0x43 && Rx_Buf[5]==0x43)
		       {
			   Turn_Left(100);
			   }
		  if(Rx_Buf[2]==0x44 && Rx_Buf[3]==0x44 && Rx_Buf[4]==0x44 && Rx_Buf[5]==0x44)
	           {
			   Turn_Right(100);
			   }	  
		  if(Rx_Buf[2]==0x45 && Rx_Buf[3]==0x45 && Rx_Buf[4]==0x45 && Rx_Buf[5]==0x45)
		       {
			   Stop();
			   }
		  if(Rx_Buf[2]==0x46 && Rx_Buf[3]==0x46 && Rx_Buf[4]==0x46 && Rx_Buf[5]==0x46)
		       {
			   Circle(200);// 走弧线
			   }		
		  if(Rx_Buf[2]==0x47 && Rx_Buf[3]==0x47 && Rx_Buf[4]==0x47 && Rx_Buf[5]==0x47)
		       {
			   Go_Ahead(200);  //以下为走矩形
			   Turn_Left(100);
			   Go_Ahead(200);
			   Turn_Left(100);
			   Go_Ahead(200);
			   Turn_Left(100);
			   Go_Ahead(200);
			   Turn_Left(100);
			   }
		  if(Rx_Buf[2]==0x48 && Rx_Buf[3]==0x48 && Rx_Buf[4]==0x48 && Rx_Buf[5]==0x48)
		       {
			     unsigned int i;
                 for(i=0;i<3;i++)
                {
                   Eight_R(50);
                   Eight_L(50);
                }	// 走8字
			    //Eight(3);
			   }	
		 if(Rx_Buf[2]==0x49 && Rx_Buf[3]==0x49 && Rx_Buf[4]==0x49 && Rx_Buf[5]==0x49)
		       {
			       xuanya();// 躲避前方障碍
			   }	
     
	   }
   
}
/*************************************************************
                 串口接收后的处理函数
*************************************************************/
void Send_Char(unsigned char c)
{
 	 UDR0=c;
	 while(!(MCUSR & 0x40));
	     MCUSR|=0x40;
}
/*************************************************************
                 串口接收中断
*************************************************************/
void uart0_rx_isr(void)
{              
          mid=UDR0; //先把数据从UDR中取出来
	 /* 判断是否收到字符'$',其数值为0x24,置开始接收标志位*/
	  if ((!Flag_StartRec) && (mid == 0x24))
	     {
		   Flag_StartRec = 1;
		   PORTB=0X0D;	
	     }		
	  if  (Flag_StartRec)
	     {
		   if (rCount <10)
		      {
			   Rx_Buf[rCount] = mid;
			   rCount ++;		
		      }
		 
		   /* 判断是否收到字符'*',其数值为0x2A,根据接收的指令设置相应标志位 */
		   if (Rx_Buf[rCount -1] == 0x2A)
		      {	
                rCount  = 0;		
			    Flag_StartRec = 0;
				PORTB=0X0E;
			    Dispose();
				
			  }

		} 
	UCSR0B|=(1<<UDRIE0);	//使能发送中断
}
void uart0_tx_isr(void)
{     
	 UDR0=mid;		 		 
	 UCSR0B =(1<<RXEN0)|(1<<RXCIE0)|(1<<TXEN0);	 //关闭发送中断,使能接受中断
}	
/*************************************************************
                 串口初始化
*************************************************************/
void Uart_Init()
{
 DDRD=0X02;
 PORTD=0X03;    //PD.0上拉 0000 0011
 UCSR0B = 0x00; //设置UBRR前关闭控制
 UCSR0A = 0x00;
 UBRR0L=(fosc/16/(baud+1))%256;
 UBRR0H=(fosc/16/(baud+1))/256;//设置UBRR
 UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);//8位数据+1位STOP位
 UCSR0B=(1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);//启动使能中断
}
/*************************************************************
                 主函数
*************************************************************/
void main()
{
 Car_Init();	  //端口初始化
 Nfr401_Init();   //无线模块初始化
 Uart_Init();     //串口初始化

 DDRB=0XFF;
 PORTB=0XFF;       
 SEI();
 //UCSR0B =(1<<RXEN0)|(1<<RXCIE0)|(1<<TXEN0);	 //关闭发送中断,使能接受中断
 while(1)
  {    
     DDRD=0XF0;
	 //Go_Ahead(100);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -