![]() |
中国面包师贴吧-楼主(阅:2056/回:0)一种具有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直流电机,所以它可以进行行走,抬手,伸手等多种动作。 本实用新型解决其技术问题所采用的技术方案是:一种具有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)采样得到的温度值发送给计算机。单片机的程序可以在百度网盘https://pan.baidu.com/s/14Uj9J_T1WzvOVJPuoOI-cw下载。 单片机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 ucharunsigned char #include <intrins.h> #define OP_READ 0xa1 // 器件地址以及读取操作 #define OP_WRITE 0xa0 //器件地址以及写入操作 #define MAX_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 * ******************************************************************************/ #defineV_TH0 0XFF #defineV_TL0 0XF6 #define V_TMOD0X01 #defineV_TH1 0XFF #defineV_TL1 0XF6 #defineV_TH2 0XFF #defineV_TL2 0XF6 #define uintunsigned int #define ucharunsigned char #define nop_nop_() sbitadcs=P3^7;//P3.7连接ADC0832的CS使能端 sbit adclk=P1^0; //P1.0连接ADC0832的时钟输入口 sbitaddin=P1^1;//ADC0832的D0,D1是分时工作的,所以这两个端口可以接在同一个IO口P1.1 uchar addata; bit y; //位数据,以0或1区倍两个通道的输入和输出 unsigned charcode 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 charshin(); bitshout(unsigned char write_data); unsigned charread_random(unsigned char random_addr); void write_byte(unsigned char addr, unsigned char write_data); voidfill_byte(unsigned char fill_data); voiddelayms(unsigned char ms); voidinit_sys(void); /*系统初始化函数*/ voidDelay5Ms(void); void delay1(unsigned char m); unsigned charZKB1,ZKB2,ZKB3,ZKB4,ZKB5,ZKB6,ZKB7,ZKB8,ZKB9,ZKB10,ZKB11,ZKB12,ZKB13,ZKB14,ZKB15,ZKB16,ZKB17,ZKB18; unsigned charZKB19,ZKB20,ZKB21,ZKB22,ZKB23,ZKB24,ZKB25,ZKB26,ZKB27,ZKB28,ZKB29,ZKB30,ZKB31,ZKB32; unsigned char key_s, key_v, tmp,tmp1; char codestr[]={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(); bit scan_key(); void proc_key(); voiddelayms(unsigned char ms); void delayms1(unsigned char a) ; voidsend_char(unsigned char txd); unsignedchar 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 charn=0; //n为节拍常数变量 歌曲为八月桂花香 unsigned charcode 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; } /****************************************************** *函数功能:对系统进行初始化,包括定时器初始化和变量初始化*/ voidinit_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; } //延时 voidDelay5Ms(void) { unsigned intTempCyc = 1000; while(TempCyc--); } /*中断函数*/ void timer0(void)interrupt 1 using 2 { static ucharclick=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(unsignedchar 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 charshin() // 从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); } bitshout(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应答位 } voidwrite_byte(unsigned char addr, unsigned char write_data) // 在指定地址addr处写入数据write_data { start(); shout(OP_WRITE); shout(addr); shout(write_data); stop(); delayms(10); // 写入周期 } voidfill_byte(unsigned char fill_data) // 填充数据fill_data到EEPROM内 { unsigned char i; for(i = 0; i < MAX_ADDR; i++) { write_byte(i, fill_data); } } unsigned charread_current() // 在当前地址读取 { unsigned char read_data; start(); shout(OP_READ); read_data = shin(); stop(); return read_data; } unsigned charread_random(unsigned char random_addr) // 在指定地址读取 { start(); shout(OP_WRITE); shout(random_addr); return(read_current()); } voiddelayms(unsigned char ms) // 延时子程序 { unsigned char i; while(ms--) { for(i = 0; i < 120; i++); } } voidadstart()//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; // 第一个脉冲 // nop; 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_()循环位移 //nop; //adclk=1; //nop; nop; //adclk=0; //nop; //nop; //} adcs=1; } //void timer2(void) interrupt 4 using 1 //{ //adstart(); //adread(); //} //voidint0() interrupt 1 //采用中断0 控制节拍 //{ //TH1=0xd8; // TL1=0xef; // n--; //} void delay1(unsigned char m) //控制频率延时 { unsigned i=3*m; while(--i); } voiddelayms1(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 ucharclick=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方波。 /****************************************************** *函数功能:对系统进行初始化,包括定时器初始化和变量初始化*/ voidinit_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信号,并连接一路直流电机。 图1 图1 |
| 发帖须知: 1,发帖请遵守《计算机信息网络国际联网安全保护管理办法》、《互联网信息服务管理办法》、 《互联网电子公告服务管理规定》、《维护互联网安全的决定》等法律法规。 2,请对您的言论负责,我们将保留您的上网记录和发帖信息。 3,在此发帖表示认同我们的条款,我们有权利对您的言论进行审核、删除或者采取其他在法律、地方法规等条款规定之内的管理操作。 |