一种具有17路可调PWM直流电机的串口遥控机器人

一种具有17路可调PWM直流电机的串口遥控机器人
一种具有17路可调PWM直流电机的串口遥控机器人

技术领域
本实用新型涉及一种具有17路PWM直流电机的串口遥控机器人,尤其是一种可以用串口无线WIFI遥控的智能机器人。


背景技术
现有常规遥控机人按照无线电信号的遥控进行动作,也可以按照存储在寄存器里面的程序动作,但是动作电机较少,一般只有4路PWM直流电机,且PWM方波的频率,占空比保持固定,这对机器人的行动带来很大的不便。一种具有17路可调PWM直流电机的串口遥控机器人是一种具有17路可调PWM频率、占空比的直流电机的机器人,操作者可以使用计算机串口WIFI信号对它的17路直流电机进行遥控,它也可以按照其控制电路中的24C04铁电存储器里面的数据,读取ADC0832芯片采样的温度值,并通过串口WIFI信号发送到操作者的电脑。


实用新型内容
为了解决常规遥控机器人动作电机较少,动作单一的缺点,一种具有17路可调PWM直流电机的串口遥控机器人提供了一种具有17路可调PWM直流电机进行串口WIFI信号遥控动作的机器人。它可以按照电路中的24C04铁电存储器里面的数据,读取ADC0832芯片采样的温度值,在单片机STC12C5A60S2的控制下进行动作,也可以按照操作人员的计算机串口WIFI信号的遥控进行动作。由于它具有17路PWM直流电机,所以它可以进行行走,抬手,伸手等多种动作。操作人员可以将计算机的232串口单片机STC12C5A60S2的232串口连接起来,再通过COMMIX串口调试助手软件在计算机上面发送数据控制单片机STC12C5A60S2所产生的PWM波形的占空比,频率等参数,进而实现对直流电机的控制。操作人员在计算机上面的COMMIX串口调试助手软件发送十六进制数11,单片机STC12C5A60S2所产生的PWM波形的占空比,频率都减小,同时计算机上面的COMMIX串口调试助手软件收到单片机STC12C5A60S2返回的十六进制数11和ADC0832芯片所采集的十六进制温度数据。当温度热电阻发生变化时,ADC0832芯片所采集的温度数据也会发生变化。操作人员在计算机上面的COMMIX串口调试助手软件发送十六进制数AA,单片机STC12C5A60S2所产生的PWM波形的占空比,频率都增大。操作人员在计算机上面的COMMIX串口调试助手软件发送十六进制数FF,单片机STC12C5A60S2所产生的PWM波形的占空比,频率达到最大。
本实用新型解决其技术问题所采用的技术方案是:一种具有17路可调PWM直流电机的串口遥控机器人是一种可以被WIFI串口信号遥控的机器人,它的17路PWM方波的频率和占空比都可以通过计算机WIFI串口信号进行调节。它依靠外壳下面装配的17路PWM直流电机在操作人员的计算机串口WIFI信号的遥控下进行转动,行走等各种动作。它可以在电机的转动下进行移动,行走,抬手等等动作。同时,它也可以按照控制电路中的24C04铁电存储器(5)里面的数据,在STC12C5A60S2单片机(4)的控制下进行电机的转动等动作,它可以将ADC0832芯片(6)采样得到的温度值通过WIFI串口发送到计算机。它的控制电路如图1所示。在图1中,STC12C5A60S2单片机(4)的P1中的P1.2, P1.3, P1.4, P1.5, P1.6,P1.7端口,P3 中的P3.2, P3.5, P3.6端口,P2中的P2.0,P2.1,P2.2,P2.3,P2.4,P2.5,P2.6,P2.7端口在定时器TIME0的控制下产生17路PWM方波,上面总共17路IO口,每个IO口产生一路PWM信号,总共17路PWM控制方波信号。操作人员通过遥控计算机的WIFI串口发送数据到STC12C5A60S2单片机(4),就可以改变上述端口的PWM方波信号的频率、占空比等。同时也可以得到ADC0832芯片(6)采样得到的温度值。WIFI模块连接在单片机STC12C5A60S2(4)的串口上面,它接收操作人员发出的数据,然后单片机STC12C5A60S2 (4)按照程序减少或增加PWM方波的占空比,增加或减少频率。同时单片机(4)按照铁电存储器24C04(5)中的数据控制上面的PWM方波信号。操作人员通过USB串口(1),经过芯片PL2303HX(3),给单片机下载程序。5V开关电源(2)给单片机提供5V直流电。ULN2003D驱动芯片(7)使单片机P1,P2,P3端口的PWM信号稳定保持不变

操作人员通过计算机串口发送十六进制数01,单片机(4)的P0.0端口就是高电平,同时单片机将01发送给计算机,也将ADC0832芯片(6)采样得到的温度值发送给计算机。操作人员通过计算机串口发送十六进制数02,单片机(4)的P0.1端口就是高电平,同时单片机将02发送给计算机,也将ADC0832芯片(6)采样得到的温度值发送给计算机。操作人员通过计算机串口发送十六进制数04,单片机(4)的P0.2端口就是高电平,同时单片机将04发送给计算机,也将ADC0832芯片(6)采样得到的温度值发送给计算机。单片机的程序可以在百度网盘

 

下载。微云文件分享:20PWM机器人下载地址:
 

单片机STC12C5A60S2(4)的控制程序是在keill4编译环境下,通过C语言编译并通过串口下载到单片机STC12C5A60S2(4)。程序代码如下:
/******************************************************************************
*程序思路说明: *
* *
*关于频率和占空比的确定,对于12M晶振,假定PWM输出频率为1KHZ,这样定时中断次数 *
*设定为C=10,即0.01MS中断一次,则TH0=FF,TL0=F6;由于设定中断时间为0.01ms,这样可以设定占空比
可从1-100变化。即0.01ms*100=1ms *
******************************************************************************/
#include <reg52.h>
#include <INTRINS.H>
#define uchar unsigned char
#include <intrins.h>
#defineOP_READ0xa1// 器件地址以及读取操作
#defineOP_WRITE 0xa0// 器件地址以及写入操作
#defineMAX_ADDR 0x7f// AT24C02最大地址
/*****************************************************************************
* TH0和TL0是计数器0的高8位和低8位计数器,计算办法:TL0=(65536-C)%256; *
* TH0=(65536-C)/256,其中C为所要计数的次数即多长时间产生一次中断;TMOD是计数器*
* 工作模式选择,0X01表示选用模式1,它有16位计数器,最大计数脉冲为65536,最长时 *
* 间为1ms*65536=65.536ms *
******************************************************************************/
#define V_TH0 0XFF
#define V_TL0 0XF6
#define V_TMOD 0X01
#define V_TH1 0XFF
#define V_TL1 0XF6
#define V_TH2 0XFF
#define V_TL2 0XF6
#define uint unsigned int
#define uchar unsigned char
#define nop _nop_()
sbit adcs=P3^7;//P3.7连接ADC0832的CS使能端
sbit adclk=P1^0; //P1.0连接ADC0832的时钟输入口
sbit addin=P1^1;//ADC0832的D0,D1是分时工作的,所以这两个端口可以接在同一个IO口P1.1
uchar addata;
bit y; //位数据,以0或1区倍两个通道的输入和输出
unsigned char code dis_code[] = {0x7e,0xbd,0xdb,0xe7,0xdb,0xbd,0x7e,0xff};
// 写入到AT24C01的数据串
sbit SDA = P3^4;
sbit SCL = P3^3;
void adread();
void adstart();
void start();
void stop();
unsigned char shin();
bit shout(unsigned char write_data);
unsigned char read_random(unsigned char random_addr);

void write_byte( unsigned char addr, unsigned char write_data);
void fill_byte(unsigned char fill_data);
void delayms(unsigned char ms);
void init_sys(void); /*系统初始化函数*/

void Delay5Ms(void);
void delay1 (unsigned char m);
unsigned char ZKB1,ZKB2,ZKB3,ZKB4,ZKB5,ZKB6,ZKB7,ZKB8,ZKB9,ZKB10,ZKB11,ZKB12,ZKB13,ZKB14,ZKB15,ZKB16,ZKB17,ZKB18;
unsigned char ZKB19,ZKB20,ZKB21,ZKB22,ZKB23,ZKB24,ZKB25,ZKB26,ZKB27,ZKB28,ZKB29,ZKB30,ZKB31,ZKB32;
unsigned char key_s, key_v, tmp,tmp1;
char code str[]={0x7e,0xbd,0xdb,0xe7,0xdb,0xbd,0x7e,0xff,0x7e,0xbd,0xdb,0xe7,0xdb,0xbd,0x7e,0xff,0x7e,0xbd,0xdb,0xe7,0xdb,0xbd,0x7e,0xff};
void send_str();
bitscan_key();
void proc_key();
void delayms(unsigned char ms);
void delayms1(unsigned char a) ;
void send_char(unsigned char txd);
unsigned char i;
unsigned char k,m; //m为频率常数变量
unsigned char s=0;
unsigned char p;
unsigned char p1=0x00,p2,p3,p4;
//本例采用89C52, 晶振为12MHZ
//关于如何编制音乐代码, 其实十分简单,各位可以看以下代码.
//频率常数即音乐术语中的音调,而节拍常数即音乐术语中的多少拍;
//所以拿出谱子, 试探编吧!
//sbit Beep = P3^7;
sbit Beep1 = P3^6;
sbit Beep2 = P3^5;
//sbit Beep3 = P3^4;
// sbit Beep4 = P3^3;
sbit Beep5 = P3^2;
//sbit Beep6 = P3^1;
//sbit Beep7 = P3^0;
sbit Beep8 = P1^7;
sbit Beep9 = P1^6;
sbit Beep10 = P1^5;
sbit Beep11 = P1^4;
sbit Beep12 = P1^3;
sbit Beep13 = P1^2;
//sbit Beep14 = P1^1;
//sbit Beep15 = P1^0;
sbit Beep16 = P2^7;
sbit Beep17 = P2^6;
sbit Beep18 = P2^5;
sbit Beep19 = P2^4;
sbit Beep20 = P2^3;
sbit Beep21 = P2^2;
sbit Beep22 = P2^1;
sbit Beep23 = P2^0;
unsigned char n=0; //n为节拍常数变量 歌曲为八月桂花香
unsigned char code music_tab[] ={
0x18, 0x30, 0x1C , 0x10, //格式为: 频率常数, 节拍常数, 频率常数, 节拍常数,
0x20, 0x40, 0x1C , 0x10,
0x18, 0x10, 0x20 , 0x10,
0x1C, 0x10, 0x18 , 0x40,
0x1C, 0x20, 0x20 , 0x20,
0x1C, 0x20, 0x18 , 0x20,
0x20, 0x80, 0xFF , 0x20,
0x30, 0x1C, 0x10 , 0x18,
0x20, 0x15, 0x20 , 0x1C,
0x20, 0x20, 0x20 , 0x26,
0x40, 0x20, 0x20 , 0x2B,
0x20, 0x26, 0x20 , 0x20,

0x20, 0x30, 0x80 , 0xFF,
0x20, 0x20, 0x1C , 0x10,
0x18, 0x10, 0x20 , 0x20,
0x26, 0x20, 0x2B , 0x20,
0x30, 0x20, 0x2B , 0x40,
0x20, 0x20, 0x1C , 0x10,
0x18, 0x10, 0x20 , 0x20,
0x26, 0x20, 0x2B , 0x20,
0x30, 0x20, 0x2B , 0x40,
0x20, 0x30, 0x1C , 0x10,
0x18, 0x20, 0x15 , 0x20,
0x1C, 0x20, 0x20 , 0x20,
0x26, 0x40, 0x20 , 0x20,

0x2B, 0x20, 0x26 , 0x20,
0x20, 0x20, 0x30 , 0x80,
0x20, 0x30, 0x1C , 0x10,
0x20, 0x10, 0x1C , 0x10,
0x20, 0x20, 0x26 , 0x20,
0x2B, 0x20, 0x30 , 0x20,
0x2B, 0x40, 0x20 , 0x15,
0x1F, 0x05, 0x20 , 0x10,
0x1C, 0x10, 0x20 , 0x20,
0x26, 0x20, 0x2B , 0x20,
0x30, 0x20, 0x2B , 0x40,
0x20, 0x30, 0x1C , 0x10,
0x18, 0x20, 0x15 , 0x20,
0x1C, 0x20, 0x20 , 0x20,
0x26, 0x40, 0x20 , 0x20,
0x2B, 0x20, 0x26 , 0x20,
0x20, 0x20, 0x30 , 0x30,
0x20, 0x30, 0x1C , 0x10,
0x18, 0x40, 0x1C , 0x20,
0x20, 0x20, 0x26 , 0x40,
0x13, 0x60, 0x18 , 0x20,
0x15, 0x40, 0x13 , 0x40,
0x18, 0x80, 0x00
};
unsigned char code music_tab1[] ={
0x1D, 2202, 0x1D , 2902, //格式为: 频率常数, 节拍常数, 频率常数, 节拍常数, 我从山中来歌曲
0x1D, 2902, 0x1D , 2902,
0x1D, 2906, 0x1D , 2702,
0x15, 2502, 0x16 , 2702,
0x00, 2502, 0x15 , 2402,
0x16, 2208, 0x19 , 0x20,
0x00, 0x80, 0x1C, 0x20,
0x00, 0x1C, 0x10 , 0x18,
0x20, 0x15, 0x20 , 0x1C,
0x20, 0x20, 0x20 , 0x26,
0x40, 0x20, 0x20 , 0x2B,
0x20, 0x26, 0x20 , 0x20,
0x20, 0x30, 0x80 , 0xFF,
0x20, 0x20, 0x1C , 0x10,
0x18, 0x10, 0x20 , 0x20,
0x26, 0x20, 0x2B , 0x20,
0x30, 0x20, 0x2B , 0x40,
0x20, 0x20, 0x1C , 0x10,
0x18, 0x10, 0x20 , 0x20,
0x26, 0x20, 0x2B , 0x20,
0x30, 0x20, 0x2B , 0x40,
0x20, 0x30, 0x1C , 0x10,
0x18, 0x20, 0x15 , 0x20,
0x1C, 0x20, 0x20 , 0x20,
0x26, 0x40, 0x20 , 0x20,
0x2B, 0x20, 0x26 , 0x20,
0x20, 0x20, 0x30 , 0x80,
0x20, 0x30, 0x1C , 0x10,
0x20, 0x10, 0x1C , 0x10,
0x20, 0x20, 0x26 , 0x20,
0x2B, 0x20, 0x30 , 0x20,
0x2B, 0x40, 0x20 , 0x15,
0x1F, 0x05, 0x20 , 0x10,
0x1C, 0x10, 0x20 , 0x20,

0x26, 0x20, 0x2B , 0x20,
0x30, 0x20, 0x2B , 0x40,
0x20, 0x30, 0x1C , 0x10,
0x18, 0x20, 0x15 , 0x20,
0x1C, 0x20, 0x20 , 0x20,
0x26, 0x40, 0x20 , 0x20,
0x2B, 0x20, 0x26 , 0x20,
0x20, 0x20, 0x30 , 0x30,
0x20, 0x30, 0x1C , 0x10,
0x18, 0x40, 0x1C , 0x20,
0x20, 0x20, 0x26 , 0x40,
0x13, 0x60, 0x18 , 0x20,
0x15, 0x40, 0x13 , 0x40,
0x18, 0x80, 0x00
};
void main (void)
{
init_sys();
ZKB1=40; /*占空比初始值设定*/
SDA = 1;
SCL = 1;
//fill_byte(0x00);// 全部填充0xff
//adstart();
// adread();
play:
while(1)
{
//adstart();
// adread();
if(RI)// 是否有数据到来
{
RI = 0;
tmp = SBUF;// 暂存接收到的数据

//tmp1=SBUF++;
// dis_code[i]=SBUF;
// 数据传送到P0口
// str[1]=SBUF;
write_byte(0X00, tmp);
//write_byte(0X01, tmp+4);
write_byte(0X02, addata);
//write_byte(0X00, str[1]);
//write_byte(0X01, tmp1);
P0 = read_random(0X00);// 循环读取24Cxx内容,并输出到P0口
//P2= read_random(0X02);
// p1= read_random(0X00);
// p2= read_random(0X01);
//delayms(250);
send_char(tmp);// 回传接收到的数据
send_char( addata);// 回传接收到的数据
// send_str() ;
}
a: k=music_tab[s+tmp];
if(k==0x00) { s=0, delayms(1000); goto play;} //如果碰到结束符,延时1秒,回到开始再来一遍
else if(k==0xff) { s=s+1;delayms(100),TR0=0; goto a;} //若碰到休止符,延时100ms,继续取下一音符
else {m=music_tab[s++], n=music_tab[s++];} //取频率常数 和 节拍常数
TR0=1; //开定时器1
while(n!=0) Beep1=~Beep1,Beep2=~Beep2,Beep5=~Beep5,Beep8=~Beep8,Beep9=~Beep9,Beep10=~Beep10,Beep11=~Beep11,Beep12=~Beep12,Beep13=~Beep13,Beep16=~Beep16,Beep17=~Beep17,Beep18=~Beep18,Beep19=~Beep19,Beep20=~Beep20,Beep21=~Beep21,Beep22=~Beep22,Beep23=~Beep23,delay1(m); //等待节拍完成, 通过P1口输出音频(可多声道哦!)
TR0=0; //关定时器1
b: k=music_tab1[s+tmp];
if(k==0x00) { s=0, delayms(1000); goto play;} //如果碰到结束符,延时1秒,回到开始再来一遍

else if(k==0xff) { s=s+1;delayms(100),TR0=0; goto b;} //若碰到休止符,延时100ms,继续取下一音符
else {m=music_tab1[s++], n=music_tab1[s++];} //取频率常数 和 节拍常数
TR0=1; //开定时器1
while(n!=0) Beep16=~Beep16,Beep17=~Beep17,Beep18=~Beep18,Beep19=~Beep19,Beep20=~Beep20,Beep21=~Beep21,Beep22=~Beep22,Beep23=~Beep23,delay1(m); //等待节拍完成, 通过P1口输出音频(可多声道哦!)
TR0=0;
//tmp1 = str[i];
//write_byte(0X01, tmp1);
//i++;// 下一个字符
//P2 = read_random(0X01);// 循环读取24Cxx内容,并输出到P0口
// if (!P0_0) //如果按了+键,增加占空比
//{
// Delay5Ms();
// if (!P0_0)
// {
// ZKB1--;
//ZKB1=90;
// }
}
/*对占空比值限定范围*/
//if (ZKB1>99) ZKB1=1;
//if (ZKB1<1) ZKB1=99;
}
/******************************************************

*函数功能:对系统进行初始化,包括定时器初始化和变量初始化*/
void init_sys(void) /*系统初始化函数*/
{
/*定时器TIME0初始化*/
//TMOD=V_TMOD;
TH0=V_TH0;
TL0=V_TL0;
TR0=1;
ET0=1;
EA=1;
/*定时器TIME1初始化*/
TMOD = 0x20;// 定时器1工作于8位自动重载模式, 用于产生波特率
TH1 = 0xFD;// 波特率9600
TL1 = 0xFD;
SCON = 0x50;// 设定串行口工作方式
PCON &= 0xef;// 波特率不倍增
TR1 = 1;// 启动定时器1
//TR2=1;
// ET2=1;
//TMOD&=0x0f;
//TMOD|=0x01;
TH0=0xd8;
TL0=0xef;
IE=0x82;
//IE = 0x0;// 禁止任何中断
// TH2=V_TH2;
// TL2=V_TL2;
// TR2=1;
// ET2=1;
//EA=1;
}
//延时
void Delay5Ms(void)
{
unsigned int TempCyc = 1000;
while(TempCyc--);
}
/*中断函数*/
void timer0(void) interrupt 1 using 2
{
static uchar click=0; /*中断次数计数器变量*/
adstart();
adread();
//TH0=V_TH0; /*恢复定时器初始值*/
//TL0=V_TL0;
TH0=0xd8;
TL0=0xef;
n--;
//++click;
//if (click>=100) click=0;
//if (click<=ZKB1) /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/
// P1_0=0;
//else
//P1_0=1;
//if (click<=ZKB2)
//P1_1=0;
//else
//P1_1=1;
//if (click<=ZKB3) /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/
//P1_2=0;
//else
//P1_2=1;
}

void send_char(unsigned char txd)
// 传送一个字符
{
SBUF = txd;
while(!TI);// 等特数据传送
TI = 0;// 清除数据传送标志
}
void send_str()
// 传送字串
{
unsigned char i = 0;
while(str[i] != '\0')
{
SBUF = str[i];
while(!TI);// 等特数据传送
TI = 0;// 清除数据传送标志
i++;// 下一个字符
}
}
void start()
// 开始位
{
SDA = 1;
SCL = 1;
_nop_();
_nop_();
SDA = 0;
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0;
}
void stop()
// 停止位
{
SDA = 0;
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 1;
}
unsigned char shin()
// 从AT24Cxx移入数据到MCU
{
unsigned char i,read_data;
for(i = 0; i < 8; i++)
{
SCL = 1;
read_data <<= 1;
read_data |= (unsigned char)SDA;
SCL = 0;
}
return(read_data);
}
bit shout(unsigned char write_data)
// 从MCU移出数据到AT24Cxx
{
unsigned char i;
bit ack_bit;
for(i = 0; i < 8; i++)// 循环移入8个位
{
SDA = (bit)(write_data & 0x80);
_nop_();
SCL = 1;
_nop_();
_nop_();
SCL = 0;
write_data <<= 1;
}
SDA = 1;// 读取应答
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ack_bit = SDA;
SCL = 0;
return ack_bit;// 返回AT24Cxx应答位
}
void write_byte(unsigned char addr, unsigned char write_data)
// 在指定地址addr处写入数据write_data
{
start();

shout(OP_WRITE);
shout(addr);
shout(write_data);
stop();
delayms(10);// 写入周期
}
void fill_byte(unsigned char fill_data)
// 填充数据fill_data到EEPROM内
{
unsigned char i;
for(i = 0; i < MAX_ADDR; i++)
{
write_byte(i, fill_data);
}
}
unsigned char read_current()
// 在当前地址读取
{
unsigned char read_data;
start();
shout(OP_READ);
read_data = shin();
stop();
return read_data;
}
unsigned char read_random(unsigned char random_addr)
// 在指定地址读取
{
start();
shout(OP_WRITE);
shout(random_addr);
return(read_current());
}
void delayms(unsigned char ms)
// 延时子程序
{
unsigned char i;
while(ms--)
{
for(i = 0; i < 120; i++);
}
}
void adstart()//ADC0832开始子函数
{
//、说明ADC0832芯片资料。CS使能=1.禁止,CLK和D0/D1随意
// 需要转换时,宣讲CS=0使能,并保持到数据传输完成
//单片机向CLK输出脉冲,前3个脉冲为启动和通道控制,脉冲上升沿有效;第一个脉冲前
//使D1=1,启动信号传输,在第二个和第三个脉冲前分贝输入两位数字选择通道,10=CH0,11=CH1
adcs=1; // ;一个转换周期开始
adclk=0;
adcs=0; // CS置0,片选有效
addin=1; //;DI置1,起始位
adclk=1;// 第一个脉冲
/ p;
addin=0; // 在负跳变之前加一个DI反转操作
adclk=0;
addin=1; //DI置1,设为单通道
adclk=1; // 第二个脉冲
addin=0;
adclk=0;
addin=0;
//DI置0,选择通道0
adclk=1; //第三个脉冲
addin=1;
adclk=0;
nop;
adclk=1; //第四个脉冲


}
void adread() //adc0832的数据读取子函数
{
//根据芯片说明:从第4和脉冲ADC0832开始输出数据
//4-19个脉冲分别从高到低输出(D7--D0)然后公用最低位D0,从低到高再(D0--D7)输出一次
uchar h;
//uchar dat0; //dat0读取12--19脉冲作为数据效验,这里不要
addata=0;
for(h=0;h<8;h++)
{
adclk=1;
nop;
nop;
adclk=0;
nop;
addata<<=1; //必须选为以后读取。否则最高位会丢失
addata|=addin; //addata值同addin口的值进行或运算后赋值给addata
nop;
}
//如果不要效验,12-19脉冲可以不再使用和读取,所以下面8位的循环可以去掉,直接将CS使能值1
//for(h=0;h<8;h++)
//{
//dat0|=addin; //因为上一组8位的末位是和这8位共用D0数据,所以这里需要选读取再脉冲
//dat0=_cror_(dat0,1); //这里需要使用的——coror_()循环位移
/ p;
//adclk=1;
/ p;
nop;
//adclk=0;
/ p;
/ p;
//}
adcs=1;
}
//void timer2(void) interrupt 4 using 1
//{
//adstart();
//adread();
//}
//void int0() interrupt 1 //采用中断0 控制节拍
//{ //TH1=0xd8;
// TL1=0xef;
// n--;
//}
void delay1 (unsigned char m) //控制频率延时
{
unsigned i=3*m;
while(--i);
}
void delayms1(unsigned char a) //豪秒延时子程序
{
while(--a); //采用while(--a) 不要采用while(a--); 各位可编译一下看看汇编结果就知道了!
}
上述程序中,单片机STC12C5A60S2串口只能接收到一个字节的16进制数,所以每次必须发送一个字节的16进制数,这样单片机才能接收。程序中的下面内容:
if(RI)// 是否有数据到来
{
RI = 0;

tmp = SBUF;// 暂存接收到的数据
//tmp1=SBUF++;
// dis_code[i]=SBUF;
// 数据传送到P0口
// str[1]=SBUF;
write_byte(0X00, tmp);
//write_byte(0X01, tmp+4);
write_byte(0X02, addata);
//write_byte(0X00, str[1]);
//write_byte(0X01, tmp1);
P0 = read_random(0X00);// 循环读取24Cxx内容,并输出到P0口
//P2= read_random(0X02);
// p1= read_random(0X00);
// p2= read_random(0X01);
//delayms(250);
send_char(tmp);// 回传接收到的数据
send_char( addata);// 回传接收到的数据
// send_str() ;
}
这段代码实现的内容是将串口接收的一个字节数据存储到24C04中的0X00寄存器中,并输出到单片机的P0端口,并赋值给p1,最后有将接收到的数据从串口发送出去。
a: k=music_tab[s+tmp];
if(k==0x00) { s=0, delayms(1000); goto play;} //如果碰到结束符,延时1秒,回到开始再来一遍
else if(k==0xff) { s=s+1;delayms(100),TR0=0; goto a;} //若碰到休止符,延时100ms,继续取下一音符
else {m=music_tab[s++], n=music_tab[s++];} //取频率常数 和 节拍常数

TR0=1; //开定时器1
while(n!=0) Beep1=~Beep1,Beep2=~Beep2,Beep5=~Beep5,Beep8=~Beep8,Beep9=~Beep9,Beep10=~Beep10,Beep11=~Beep11,Beep12=~Beep12,Beep13=~Beep13,Beep16=~Beep16,Beep17=~Beep17,Beep18=~Beep18,Beep19=~Beep19,Beep20=~Beep20,Beep21=~Beep21,Beep22=~Beep22,Beep23=~Beep23,delay1(m); //等待节拍完成, 通过P1口输出音频(可多声道哦!)
TR0=0; //关定时器1
b: k=music_tab1[s+tmp];
if(k==0x00) { s=0, delayms(1000); goto play;} //如果碰到结束符,延时1秒,回到开始再来一遍
else if(k==0xff) { s=s+1;delayms(100),TR0=0; goto b;} //若碰到休止符,延时100ms,继续取下一音符
else {m=music_tab1[s++], n=music_tab1[s++];} //取频率常数 和 节拍常数
TR0=1; //开定时器1
while(n!=0) Beep16=~Beep16,Beep17=~Beep17,Beep18=~Beep18,Beep19=~Beep19,Beep20=~Beep20,Beep21=~Beep21,Beep22=~Beep22,Beep23=~Beep23,delay1(m); //等待节拍完成, 通过P1口输出音频(可多声道哦!)
TR0=0;
这段代码实现的功能是将music_tab[s+tmp],music_tab1[s+tmp]数组赋值给端口P0,P3,P2,使它们产生频率,占空比时时可变的PWM方波。
/*中断函数*/
void timer0(void) interrupt 1 using 2
{
static uchar click=0; /*中断次数计数器变量*/
adstart();
adread();

//TH0=V_TH0; /*恢复定时器初始值*/
//TL0=V_TL0;
TH0=0xd8;
TL0=0xef;
n--;
//++click;
//if (click>=100) click=0;
//if (click<=ZKB1) /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/
// P1_0=0;
//else
//P1_0=1;
//if (click<=ZKB2)
//P1_1=0;
//else
//P1_1=1;
//if (click<=ZKB3) /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/
//P1_2=0;
//else
//P1_2=1;
}
这段代码的功能是利用定时器TIME0产生PWM方波。
/******************************************************
*函数功能:对系统进行初始化,包括定时器初始化和变量初始化*/
void init_sys(void) /*系统初始化函数*/
{
/*定时器TIME0初始化*/
//TMOD=V_TMOD;
TH0=V_TH0;
TL0=V_TL0;
TR0=1;
ET0=1;
EA=1;
/*定时器TIME1初始化*/
TMOD = 0x20;
// 定时器1工作于8位自动重载模式, 用于产生波特率
TH1 = 0xFD;// 波特率9600
TL1 = 0xFD;

SCON = 0x50;// 设定串行口工作方式
PCON &= 0xef;// 波特率不倍增

TR1 = 1;// 启动定时器1
//TR2=1;
// ET2=1;
//TMOD&=0x0f;
//TMOD|=0x01;
TH0=0xd8;
TL0=0xef;
IE=0x82;
//IE = 0x0;// 禁止任何中断
// TH2=V_TH2;
// TL2=V_TL2;
// TR2=1;
// ET2=1;
//EA=1;
}


这段代码的功能是利用初始化定时器TIME1,进行串口数据接收或发送。
上述的一种具有17路PWM直流电机的串口遥控机器人,所述的是一种具有17路可调PWM直流电机的串口WIFI遥控机器人。


附图说明
下面结合附图和实施例对本实用新型进一步说明。
图1为本实用电路图。
图1中,1.USB接口,2.5V开关电源,3.PL2303HX芯片,4.12C5A60S2单片机,5.24C04芯片,6.ADC0832芯片,7.ULN2003D。


具体实施方式
图1中,单片机STC12C5A60S2(4)的P3.0,P3.1端口连接WIFI模块,单片机STC12C5A60S2(4)的P3.3,P3.4端口连接24C04(5)存储器。单片机STC12C5A60S2(4)的P3.7端口连接ADC0832芯片(6)。STC12C5A60S2(4)的P2中的P2.0,P2.1,P2.2,P2.3,P2.4,P2.5,P2.6连接电源驱动芯片ULN2003(7)。STC12C5A60S2(4)的P3中的P3.0,P3.1连接芯片PL2303HX。ULN2003(3)的15脚,16脚连接USB端口(1)。5V直流电源(1)连接单片机STC12C5A60S2(4)的20脚,40脚。STC12C5A60S2(4)的P1中的 P1.2, P1.3, P1.4, P1.5, P1.6,P1.7端口,P3 中的P3.2, P3.5, P3.6端口,P2中的P2.0,P2.1,P2.2,P2.3,P2.4,P2.5,P2.6,P2.7上面总共17路IO口,每个IO口连接一路直流电机。
图1中,单片机STC12C5A60S2(4)经过芯片PL2302HX(3)从串口接收或发送数据到USB端口(1),单片机STC12C5A60S2(4)从24C04(5)中读取或写入数据。单片机STC12C5A60S2(4)将芯片ADC0832(6)采集的到的温度数据通过串口发送给操作人员的计算机。ULN2003芯片(7)保持单片机P1,P2,P3端口上输出的PWM信号的稳定。5V开关电源(2)通过开关给单片机(4)供电。STC11F60单片机(1)的P1中的P1.2, P1.3, P1.4, P1.5, P1.6,P1.7端口,P3 中的P3.2, P3.5, P3.6端口,P2中的P2.0,P2.1,P2.2,P2.3,P2.4,P2.5,P2.6,P2.7上面总共17路IO口,每个IO口产生一路PWM信号,并连接一路直流电机。

 
 
 

猜你喜欢

转载自www.cnblogs.com/zgdcnyhl/p/12344764.html
今日推荐