📄 new_wuxian.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 + -