有两个51单片机,二者串口通信,摇杆用了一个AD转换模块以后想做一个四足机器人
//接收机,用于驱动舵机
#include "reg52.h"
//控制8个舵机
sbit PWM0=P1^0;
sbit PWM1=P1^1;
sbit PWM2=P1^2;
sbit PWM3=P1^3;
sbit PWM4=P1^4;
sbit PWM5=P1^5;
sbit PWM6=P1^6;
sbit PWM7=P1^7;
int jishu_max=200,jishu_min=0,jishu=0,PWM0_H,PWM1_H,PWM2_H,PWM3_H,PWM4_H,PWM5_H,PWM6_H,PWM7_H;
int gaibian=0;
//static int time=0;//当前是否为空闲时间
char da[10];//接收串口数据
int i=0,temp;//temp 中间值,i 记录接收字符个数
void tim() interrupt 1
{
jishu=jishu+1;
if(jishu<26)
{
if(jishu==PWM0_H)
{
PWM0=0;
}
if(jishu==PWM1_H)
{
PWM1=0;
}
if(jishu==PWM2_H)
{
PWM2=0;
}
if(jishu==PWM3_H)
{
PWM3=0;
}
if(jishu==PWM4_H)
{
PWM4=0;
}
if(jishu==PWM5_H)
{
PWM5=0;
}
if(jishu==PWM6_H)
{
PWM6=0;
}
if(jishu==PWM7_H)
{
PWM7=0;
}
}
else
{
if(jishu==jishu_max)//到了20ms
{
// time=0;
jishu=0;
PWM0=1;
PWM1=1;
PWM2=1;
PWM3=1;
PWM4=1;
PWM5=1;
PWM6=1;
PWM7=1;
}
// else
// {
// time=1;
// }
}
}
void InitTimer0(void)
{
TMOD = 0x22;
TH0 = 0x0A4;
TL0 = 0x0A4;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void InitUART(void)
{
SCON = 0x50;
TH1 = 0xFA;
TL1 = TH1;
PCON = 0x80;
ES=1;
IP=0x02;
TR1 = 1;
}
void SendOneByte(unsigned char c)//串口发送单个字符
{
SBUF = c;
while(!TI);
TI = 0;
}
//接收格式a05~a25
void UARTInterrupt(void) interrupt 4
{
if((RI==1) && (jishu>26) &&(jishu<196))//jishu在26到196范围内,代表为空闲时间
{
// time=0;// 每个周期的空闲时间里只允许改变1次PWM值
RI = 0;
da[i]=SBUF;
i=i+1;
if((da[0]=='a')|| (da[0]=='b')||(da[0]=='c')||(da[0]=='d')|| (da[0]=='e')||(da[0]=='f')||(da[0]=='g')|| (da[0]=='h'))//a,b,c....分别对应舵机
{
gaibian=1; //收到的字符串收个字符符合,准备改变pwm_h的值
if((gaibian==1) && (i==2))
{
gaibian=0;
temp=da[1]/1;
i=0;
if((temp<=25) &&(temp>=5))
{
switch(da[0])
{
case 'a':PWM0_H=temp;break;
case 'b':PWM1_H=temp;break;
case 'c':PWM2_H=temp;break;
case 'd':PWM3_H=temp;break;
case 'e':PWM4_H=temp;break;
case 'f':PWM5_H=temp;break;
case 'g':PWM6_H=temp;break;
case 'h':PWM7_H=temp;break;
}
}
}
}
else
{
gaibian=0;
i=0;
}
}
else
{
RI=0;
i=0;
TI = 0;
}
}
int main()
{
// time=0;
P1=1;
InitTimer0();//定时器初始化,每100us溢出
InitUART();//串口初始化
PWM0_H=25;//5~25 修改这,高电平持续的时间:t=PWM_H*100 (单位:us)
PWM1_H=25;//5~25 修改这
PWM2_H=25;//5~25 修改这
PWM3_H=25;//5~25 修改这
PWM4_H=25;//5~25 修改这
PWM5_H=25;//5~25 修改这
PWM6_H=25;//5~25 修改这
PWM7_H=25;//5~25 修改这
while(1);
}
发送机,用于连接摇杆,并发送角度信号
#include<reg52.h> //包含单片机寄存器的头文件
#include <I2C.H>
#define uchar unsigned char
#define PCF8591 0x90 //PCF8591 地址
// 变量定义
unsigned char AD_CHANNEL;
unsigned long xdata LedOut[8];
unsigned int D[32];
sbit P2_0 = P2^0;
sbit P2_1 = P2^1;
sbit P2_2 = P2^2;
sbit P2_3 = P2^3;
unsigned char date;
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
0xf8,0x80,0x90};
// 函数申明
void display();
void delay(uchar i);
bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val);
bit ISendByte(unsigned char sla,unsigned char c);
unsigned char IRcvByte(unsigned char sla);
void Initial_com(void);
int zhuanhuan(float g)
{
float hh;
hh=g/1;
return hh;
}
//******************************************************************/
main()
{
Initial_com();
while(1)
{
/********以下AD-DA处理*************/
switch(AD_CHANNEL)
{
case 0: ISendByte(PCF8591,0x41);
D[0]=IRcvByte(PCF8591); //ADC0 模数转换1 光敏电阻
break;
case 1: ISendByte(PCF8591,0x42);
D[1]=IRcvByte(PCF8591); //ADC1 模数转换2 热敏电阻
break;
case 2: ISendByte(PCF8591,0x43);
D[2]=IRcvByte(PCF8591); //ADC2 模数转换3 悬空
break;
case 3: ISendByte(PCF8591,0x40);
D[3]=IRcvByte(PCF8591); //ADC3 模数转换4 可调0-5v
break;
case 4: DACconversion(PCF8591,0x40, D[4]); //DAC 数模转换
break;
}
// D[4]=D[3]; //把模拟输入采样的信号 通过数模转换输出
if(++AD_CHANNEL>4) AD_CHANNEL=0;
/********以下将AD的值通过串口发送出去*************/
SBUF='a';
SBUF=(D[0]/12.5+5)/1;
while(!TI);
TI=0;
delay(100);
if(RI)
{
// date=SBUF; //单片机接受
// SBUF=date; //单片机发送
RI=0;
}
}
}
void delay(uchar i)
{
uchar j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
/*******************************************************************
DAC 变换, 转化函数
*******************************************************************/
bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val)
{
Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(0);
SendByte(c); //发送控制字节
if(ack==0)return(0);
SendByte(Val); //发送DAC的数值
if(ack==0)return(0);
Stop_I2c(); //结束总线
return(1);
}
/*******************************************************************
ADC发送字节[命令]数据函数
*******************************************************************/
bit ISendByte(unsigned char sla,unsigned char c)
{
Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(0);
SendByte(c); //发送数据
if(ack==0)return(0);
Stop_I2c(); //结束总线
return(1);
}
/*******************************************************************
ADC读字节数据函数
*******************************************************************/
unsigned char IRcvByte(unsigned char sla)
{ unsigned char c;
Start_I2c(); //启动总线
SendByte(sla+1); //发送器件地址
if(ack==0)return(0);
c=RcvByte(); //读取数据0
Ack_I2c(1); //发送非就答位
Stop_I2c(); //结束总线
return(c);
}
//*****串口初始化函数***********
//******************************
void Initial_com(void)
{
EA=1; //开总中断
ES=1; //允许串口中断
ET1=1; //允许定时器T1的中断
TMOD=0x20; //定时器T1,在方式2中断产生波特率
PCON=0x00; //SMOD=0
SCON=0x50; // 方式1 由定时器控制
TH1=0xfd; //波特率设置为9600
TL1=0xfd;
TR1=1; //开定时器T1运行控制位
}