国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

有做瀏覽單的網(wǎng)站/百度小說風(fēng)云榜2022

有做瀏覽單的網(wǎng)站,百度小說風(fēng)云榜2022,蛋糕店網(wǎng)站建設(shè)模版,群暉打開wordpress4.9.8目錄 1.電機模塊開發(fā) 1.1 讓小車動起來 1.2 串口控制小車方向 1.3 如何進(jìn)行小車PWM調(diào)速 1.4 PWM方式實現(xiàn)小車轉(zhuǎn)向 2.循跡小車 2.1 循跡模塊使用 2.2 循跡小車原理 2.3 循跡小車核心代碼 3.跟隨/避障小車 3.1 紅外壁障模塊分析?編輯 3.2 跟隨小車的原理 3.3 跟隨小…

目錄

1.電機模塊開發(fā)

1.1 讓小車動起來

1.2 串口控制小車方向

1.3 如何進(jìn)行小車PWM調(diào)速

1.4 PWM方式實現(xiàn)小車轉(zhuǎn)向

2.循跡小車?

2.1 循跡模塊使用

2.2 循跡小車原理

2.3 循跡小車核心代碼

3.跟隨/避障小車

3.1 紅外壁障模塊分析?編輯

3.2 跟隨小車的原理

3.3 跟隨小車開發(fā)和調(diào)試代碼

3.4 超聲波模塊介紹

3.5 搖頭測距小車開發(fā)和調(diào)試代碼

4.測速小車

4.1 測速模塊

4.2 測試原理和單位換算

4.3 定時器和中斷實現(xiàn)測速開發(fā)和調(diào)試代碼

4.4 小車速度顯示在OLED屏

5.遠(yuǎn)程控制小車

5.1 藍(lán)牙控制小車

5.2 藍(lán)牙控制并測速小車

5.3 wifi控制測速小車

5.4 4g控制小車

6.語音控制小車

6.1語音模塊配置:

6.2 語音控制小車開發(fā)和調(diào)試代碼


1.電機模塊開發(fā)

L9110s概述

接通VCC,GND 模塊電源指示燈亮, 以下資料來源官方,具體根據(jù)實際調(diào)試

IA1輸入高電平,IA1輸入低電平,【OA1 OB1】電機正轉(zhuǎn);

IA1輸入低電平,IA1輸入高電平,【OA1 OB1】電機反轉(zhuǎn);

IA2輸入高電平,IA2輸入低電平,【OA2 OB2】電機正轉(zhuǎn);

IA2輸入低電平,IA2輸入高電平,【OA2 OB2】電機反轉(zhuǎn);

1.1 讓小車動起來

核心代碼:

#include "reg52.h"
#include "intrins.h"sbit RightCon1A = P3^2;
sbit RightCon1B = P3^3;sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;void Delay1000ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}void goForward()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 1;
}void goLeft()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 1;
}void goRight()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 0;
}void goBack()
{LeftCon1A = 1;LeftCon1B = 0;RightCon1A = 1;RightCon1B = 0;
}void main()
{while(1){goForward();Delay1000ms();Delay1000ms();goBack();Delay1000ms();Delay1000ms();goLeft();Delay1000ms();Delay1000ms();goRight();Delay1000ms();Delay1000ms();}
}

1.2 串口控制小車方向

  • 串口分文件編程進(jìn)行代碼整合——具體過程看課程,主要考驗C語言功底和代碼調(diào)試能力,通過現(xiàn)象來改代碼
  • 接入藍(lán)牙模塊,通過藍(lán)牙控制小車
  • 添加點動控制,如果APP支持按下一直發(fā)數(shù)據(jù),松開就停止發(fā)數(shù)據(jù)(藍(lán)牙調(diào)試助手的自定義按鍵不 能實現(xiàn)),就能實現(xiàn)前進(jìn)按鍵按下后小車一直往前走的功能

1.3 如何進(jìn)行小車PWM調(diào)速

原理: 全速前進(jìn)是LeftCon1A = 0; LeftCon1B = 1;完全停止是LeftCon1A = 0;LeftCon1B = 0;那么單位時 間內(nèi),比如20ms, 有15ms是全速前進(jìn),5ms是完全停止, 速度就會比5ms全速前進(jìn),15ms完全停止獲得的功率多,相應(yīng)的速度更快!

開發(fā):借用PWM的舵機控制代碼

核心代碼:

#include "motor.h"
#include "delay.h"
#include "uart.h"
#include "time.h"extern char speed;void main()
{Time0Init();//UartInit();while(1){speed = 10;//10份單位時間全速運行,30份停止,所以慢,20ms是40份的500usDelay1000ms();Delay1000ms();speed = 20;Delay1000ms();Delay1000ms();speed = 40;Delay1000ms();Delay1000ms();}
}//time.c
#include "motor.h"
#include "reg52.h"char speed;
char cnt = 0;void Time0Init()
{//1. 配置定時器0工作模式位16位計時TMOD = 0x01;//2. 給初值,定一個0.5出來TL0=0x33;TH0=0xFE;//3. 開始計時TR0 = 1;TF0 = 0;//4. 打開定時器0中斷ET0 = 1;//5. 打開總中斷EAEA = 1;
}void Time0Handler() interrupt 1
{cnt++;  //統(tǒng)計爆表的次數(shù). cnt=1的時候,報表了1//重新給初值TL0=0x33;TH0=0xFE;//控制PWM波if(cnt < speed){//前進(jìn)goForward();}else{//停止stop();}if(cnt == 40){//爆表40次,經(jīng)過了20mscnt = 0;  //當(dāng)100次表示1s,重新讓cnt從0開始,計算下一次的1s}}

1.4 PWM方式實現(xiàn)小車轉(zhuǎn)向

原理: 左輪定時器0調(diào)速,右輪定時器1調(diào)速,那么左轉(zhuǎn)就是右輪速度大于左輪!

核心代碼:

#include "motor.h"
#include "reg52.h"char speedLeft;
char cntLeft = 0;char speedRight;
char cntRight = 0;void Time1Init()
{//1. 配置定時器1工作模式位16位計時TMOD &= 0x0F;TMOD |= 0x1 << 4;//2. 給初值,定一個0.5出來TL1=0x33;TH1=0xFE;//3. 開始計時TR1 = 1;TF1 = 0;//4. 打開定時器1中斷ET1 = 1;//5. 打開總中斷EAEA = 1;
}void Time0Init()
{//1. 配置定時器0工作模式位16位計時TMOD = 0x01;//2. 給初值,定一個0.5出來TL0=0x33;TH0=0xFE;//3. 開始計時TR0 = 1;TF0 = 0;//4. 打開定時器0中斷ET0 = 1;//5. 打開總中斷EAEA = 1;
}void Time1Handler() interrupt 3
{cntRight++;  //統(tǒng)計爆表的次數(shù). cnt=1的時候,報表了1//重新給初值TL1=0x33;TH1=0xFE;//控制PWM波if(cntRight < speedRight){//右前進(jìn)goForwardRight();}else{//停止stopRight();}if(cntRight == 40){//爆表40次,經(jīng)過了20mscntRight = 0;  //當(dāng)100次表示1s,重新讓cnt從0開始,計算下一次的1s}}void Time0Handler() interrupt 1
{cntLeft++;  //統(tǒng)計爆表的次數(shù). cnt=1的時候,報表了1//重新給初值TL0=0x33;TH0=0xFE;//控制PWM波if(cntLeft < speedLeft){//左前進(jìn)goForwardLeft();}else{//停止stopLeft();}if(cntLeft == 40){//爆表40次,經(jīng)過了20mscntLeft = 0;  //當(dāng)100次表示1s,重新讓cnt從0開始,計算下一次的1s}}

2.循跡小車?

2.1 循跡模塊使用

  • TCRT5000傳感器的紅外發(fā)射二極管不斷發(fā)射紅外線
  • 當(dāng)發(fā)射出的紅外線沒有被反射回來或被反射回來但強度不夠大時
  • 紅外接收管一直處于關(guān)斷狀態(tài),此時模塊的輸出端為高電平,指示二極管一直處于熄滅狀態(tài)
  • 被檢測物體出現(xiàn)在檢測范圍內(nèi)時,紅外線被反射回來且強度足夠大,紅外接收管飽和
  • 此時模塊的輸出端為低電平,指示二極管被點亮
  • 總結(jié)就是一句話,沒反射回來,D0輸出高電平,滅燈

接線方式

  • VCC:接電源正極(3-5V)
  • GND:接電源負(fù)極 DO:TTL開關(guān)信號輸出0、1
  • AO:模擬信號輸出(不同距離輸出不同的電壓,此腳一般可以不接)

2.2 循跡小車原理

由于黑色具有較強的吸收能力,當(dāng)循跡模塊發(fā)射的紅外線照射到黑線時,紅外線將會被黑線吸收,導(dǎo)致 循跡模塊上光敏三極管處于關(guān)閉狀態(tài),此時模塊上一個LED熄滅。在沒有檢測到黑線時,模塊上兩個LED常亮

總結(jié)就是一句話,有感應(yīng)到黑線,D0輸出高電平 ,滅燈

2.3 循跡小車核心代碼

//main.c
#include "motor.h"
#include "delay.h"
#include "uart.h"
#include "time.h"
#include "reg52.h"
extern char speedLeft;
extern char speedRight;sbit leftSensor = P2^7;
sbit rightSensor = P2^6;void main()
{Time0Init();Time1Init();//UartInit();while(1){if(leftSensor == 0 && rightSensor == 0){speedLeft = 32;speedRight = 40;}if(leftSensor == 1 && rightSensor == 0){speedLeft = 12;//10份單位時間全速運行,30份停止,所以慢,20ms是40份的500usspeedRight = 40;}if(leftSensor == 0 && rightSensor == 1){speedLeft = 32;speedRight = 20;}if(leftSensor == 1 && rightSensor == 1){//停speedLeft = 0;speedRight = 0;}}
}//motor.c
#include "reg52.h"sbit RightCon1A = P3^2;
sbit RightCon1B = P3^3;sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;void goForwardLeft()
{LeftCon1A = 0;LeftCon1B = 1;
}void stopLeft()
{LeftCon1A = 0;LeftCon1B = 0;
}void goForwardRight()
{RightCon1A = 0;RightCon1B = 1;
}
void stopRight()
{RightCon1A = 0;RightCon1B = 0;
}void goForward()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 1;
}void goRight()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 0;
}void goLeft()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 1;
}void goBack()
{LeftCon1A = 1;LeftCon1B = 0;RightCon1A = 1;RightCon1B = 0;
}void stop()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 0;
}//delay.c
#include "intrins.h"void Delay1000ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}//time.c
#include "motor.h"
#include "reg52.h"char speedLeft;
char cntLeft = 0;char speedRight;
char cntRight = 0;void Time1Init()
{//1. 配置定時器1工作模式位16位計時TMOD &= 0x0F;TMOD |= 0x1 << 4;//2. 給初值,定一個0.5出來TL1=0x33;TH1=0xFE;//3. 開始計時TR1 = 1;TF1 = 0;//4. 打開定時器1中斷ET1 = 1;//5. 打開總中斷EAEA = 1;
}void Time0Init()
{//1. 配置定時器0工作模式位16位計時TMOD = 0x01;//2. 給初值,定一個0.5出來TL0=0x33;TH0=0xFE;//3. 開始計時TR0 = 1;TF0 = 0;//4. 打開定時器0中斷ET0 = 1;//5. 打開總中斷EAEA = 1;
}void Time1Handler() interrupt 3
{cntRight++;  //統(tǒng)計爆表的次數(shù). cnt=1的時候,報表了1//重新給初值TL1=0x33;TH1=0xFE;//控制PWM波if(cntRight < speedRight){//右前進(jìn)goForwardRight();}else{//停止stopRight();}if(cntRight == 40){//爆表40次,經(jīng)過了20mscntRight = 0;  //當(dāng)100次表示1s,重新讓cnt從0開始,計算下一次的1s}}void Time0Handler() interrupt 1
{cntLeft++;  //統(tǒng)計爆表的次數(shù). cnt=1的時候,報表了1//重新給初值TL0=0x33;TH0=0xFE;//控制PWM波if(cntLeft < speedLeft){//左前進(jìn)goForwardLeft();}else{//停止stopLeft();}if(cntLeft == 40){//爆表40次,經(jīng)過了20mscntLeft = 0;  //當(dāng)100次表示1s,重新讓cnt從0開始,計算下一次的1s}}

3.跟隨/避障小車

3.1 紅外壁障模塊分析

原理和循跡是一樣的,循跡紅外觀朝下,跟隨朝前

3.2 跟隨小車的原理

  • 左邊跟隨模塊能返回紅外,輸出低電平,右邊不能返回,輸出高電平,說明物體在左邊,需要左轉(zhuǎn)
  • 右邊跟隨模塊能返回紅外,輸出低電平,左邊不能返回,輸出高電平,說明物體在右邊,需要右轉(zhuǎn)

3.3 跟隨小車開發(fā)和調(diào)試代碼

//main.c
#include "motor.h"
#include "delay.h"
#include "reg52.h"//sbit leftSensor = P2^7;
//sbit rightSensor = P2^6;sbit leftSensor = P2^5;
sbit rightSensor = P2^4;void main()
{while(1){if(leftSensor == 0 && rightSensor == 0){goForward();}if(leftSensor == 1 && rightSensor == 0){goRight();}if(leftSensor == 0 && rightSensor == 1){goLeft();}if(leftSensor == 1 && rightSensor == 1){//停stop();}}
}//motor.c
#include "reg52.h"sbit RightCon1A = P3^2;
sbit RightCon1B = P3^3;sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;void goForward()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 1;
}void goRight()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 0;
}void goLeft()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 1;
}void goBack()
{LeftCon1A = 1;LeftCon1B = 0;RightCon1A = 1;RightCon1B = 0;
}void stop()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 0;
}//delay.c#include "intrins.h"void Delay1000ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}

3.4 超聲波模塊介紹

使用超聲波模塊,型號:HC-SR04

  • 怎么讓它發(fā)送波 Trig ,給Trig端口至少10us的高電平
  • 怎么知道它開始發(fā)了 Echo信號,由低電平跳轉(zhuǎn)到高電平,表示開始發(fā)送波
  • 怎么知道接收了返回波 Echo,由高電平跳轉(zhuǎn)回低電平,表示波回來了
  • 怎么算時間 Echo引腳維持高電平的時間! 波發(fā)出去的那一下,開始啟動定時器 波回來的拿一下,我們開始停止定時器,計算出中間經(jīng)過多少時間
  • 怎么算距離 距離 = 速度 (340m/s)* 時間/2

時序圖:

3.5 搖頭測距小車開發(fā)和調(diào)試代碼

//main.c
#include "reg52.h"
#include "hc04.h"
#include "delay.h"
#include "sg90.h"
#include "motor.h"#define MIDDLE 0
#define LEFT 1
#define RIGHT 2void main()
{char dir;double disMiddle;double disLeft;double disRight;Time0Init();Time1Init();//舵機的初始位置sgMiddle();Delay300ms();Delay300ms();dir = MIDDLE;while(1){if(dir != MIDDLE){sgMiddle();dir = MIDDLE;Delay300ms();}disMiddle = get_distance();if(disMiddle > 35){//前進(jìn)goForward();}else if(disMiddle < 10){goBack();}else{//停止stop();//測左邊距離sgLeft();Delay300ms();disLeft = get_distance();sgMiddle();Delay300ms();sgRight();dir = RIGHT;Delay300ms();disRight = get_distance();if(disLeft < disRight){goRight();Delay150ms();stop();}if(disRight < disLeft){goLeft();Delay150ms();stop();}}}
}//hc04.c
#include "reg52.h"
#include "delay.h"sbit Trig     = P2^3;
sbit Echo     = P2^2;void Time1Init()
{	TMOD &= 0x0F;		//設(shè)置定時器模式TMOD |= 0x10;TH1 = 0;TL1 = 0;//設(shè)置定時器0工作模式1,初始值設(shè)定0開始數(shù)數(shù),不著急啟動定時器
}void startHC()
{Trig = 0;Trig = 1;Delay10us();Trig = 0;
}double get_distance()
{double time;//定時器數(shù)據(jù)清零,以便下一次測距TH1 = 0;TL1 = 0;//1. Trig ,給Trig端口至少10us的高電平startHC();//2. echo由低電平跳轉(zhuǎn)到高電平,表示開始發(fā)送波while(Echo == 0);//波發(fā)出去的那一下,開始啟動定時器TR1 = 1;//3. 由高電平跳轉(zhuǎn)回低電平,表示波回來了while(Echo == 1);//波回來的那一下,我們開始停止定時器TR1 = 0;//4. 計算出中間經(jīng)過多少時間time = (TH1 * 256 + TL1)*1.085;//us為單位//5. 距離 = 速度 (340m/s)* 時間/2return  (time * 0.017);
}//delay.c
#include "intrins.h"void Delay2000ms()		//@11.0592MHz
{unsigned char i, j, k;i = 15;j = 2;k = 235;do{do{while (--k);} while (--j);} while (--i);
}void Delay10us()		//@11.0592MHz
{unsigned char i;i = 2;while (--i);
}void Delay300ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 3;j = 26;k = 223;do{do{while (--k);} while (--j);} while (--i);
}void Delay150ms()		//@11.0592MHz
{unsigned char i, j, k;i = 2;j = 13;k = 237;do{do{while (--k);} while (--j);} while (--i);
}void Delay450ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 4;j = 39;k = 209;do{do{while (--k);} while (--j);} while (--i);
}//sg90.c
#include "reg52.h"
#include "delay.h"sbit sg90_con = P1^1;int jd;
int cnt = 0;void Time0Init()
{//1. 配置定時器0工作模式位16位計時TMOD &= 0xF0;		//設(shè)置定時器模式TMOD |= 0x01;//2. 給初值,定一個0.5出來TL0=0x33;TH0=0xFE;//3. 開始計時TR0 = 1;TF0 = 0;//4. 打開定時器0中斷ET0 = 1;//5. 打開總中斷EAEA = 1;
}void sgMiddle()
{//中間位置jd = 3; //90度 1.5ms高電平cnt = 0;
}void sgLeft()
{//左邊位置jd = 5; //135度 1.5ms高電平cnt = 0;
}void sgRight()
{//右邊位置jd = 1; //0度cnt = 0;
}void Time0Handler() interrupt 1
{cnt++;  //統(tǒng)計爆表的次數(shù). cnt=1的時候,報表了1//重新給初值TL0=0x33;TH0=0xFE;//控制PWM波if(cnt < jd){sg90_con = 1;}else{sg90_con = 0;}if(cnt == 40){//爆表40次,經(jīng)過了20mscnt = 0;  //當(dāng)100次表示1s,重新讓cnt從0開始,計算下一次的1ssg90_con = 1;}}//motor.c
#include "reg52.h"sbit RightCon1A = P3^2;
sbit RightCon1B = P3^3;sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;void goForward()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 1;
}void goRight()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 0;
}void goLeft()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 1;
}void goBack()
{LeftCon1A = 1;LeftCon1B = 0;RightCon1A = 1;RightCon1B = 0;
}void stop()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 0;
}

4.測速小車

4.1 測速模塊

  • 用途:廣泛用于電機轉(zhuǎn)速檢測,脈沖計數(shù),位置限位等。
  • 有遮擋,輸出高電平;無遮擋,輸出低電平
  • 接線 :VCC 接電源正極3.3-5V
  • GND 接電源負(fù)極 DO TTL開關(guān)信號輸出
  • AO 此模塊不起作用

4.2 測試原理和單位換算

  • 輪子走一圈,經(jīng)過一個周長,C = 2x3.14x半徑= 3.14 x 直徑(6.5cm)
  • 對應(yīng)的碼盤也轉(zhuǎn)了一圈,碼盤有20個格子,每經(jīng)過一個格子,會遮擋(高電平)和不遮擋(低電平), 那么一個脈沖就是走了 3.14 * 6.5 cm /20 = 1.0205CM
  • 定時器可以設(shè)計成一秒,統(tǒng)計脈沖數(shù),一個脈沖就是1cm
  • 假設(shè)一秒有80脈沖,那么就是80cm/s

4.3 定時器和中斷實現(xiàn)測速開發(fā)和調(diào)試代碼

測試數(shù)據(jù)通過串口發(fā)送到上位機

//main.c
#include "motor.h"
#include "delay.h"
#include "uart.h"
#include "reg52.h"
#include "time.h"
#include "stdio.h"sbit speedIO = P3^2;//外部中斷0
unsigned int speedCnt = 0; //統(tǒng)計格子,脈沖次數(shù)
extern unsigned int speed;//速度
extern char signal; //主程序發(fā)速度數(shù)據(jù)的通知
char speedMes[24];  //主程序發(fā)送速度數(shù)據(jù)的字符串緩沖區(qū)void Ex0Init()
{EX0 = 1;//允許中斷//EA = 1;在串口初始化函數(shù)中已經(jīng)打開了總中斷IT0 = 1;//外部中斷的下降沿觸發(fā)
}void main()
{Time0Init();//定時器0初始化UartInit();//串口相關(guān)初始化//外部中斷初始化Ex0Init();while(1){if(signal){//定時器1s到點,把signal置一,主程序發(fā)送速度sprintf(speedMes,"speed:%d cm/s",speed);//串口數(shù)據(jù)的字符串拼裝,speed是格子,每個格子1cmSendString(speedMes);//速度發(fā)出去signal = 0;//清0speed,下次由定時器1s后的中斷處理中再置一}}
}void speedHandler() interrupt 0 //外部中斷處理函數(shù)
{speedCnt++;//碼盤轉(zhuǎn)動了一個格子
}//uart.c
#include "reg52.h"
#include "motor.h"
#include "string.h"
sbit D5 = P3^7;
#define SIZE 12sfr AUXR = 0x8E;
char buffer[SIZE];void UartInit(void)		//9600bps@11.0592MHz
{AUXR = 0x01;SCON = 0x50; //配置串口工作方式1,REN使能接收TMOD &= 0x0F;TMOD |= 0x20;//定時器1工作方式位8位自動重裝TH1 = 0xFD;TL1 = 0xFD;//9600波特率的初值TR1 = 1;//啟動定時器EA = 1;//開啟總中斷ES = 1;//開啟串口中斷
}void SendByte(char mydata)
{SBUF = mydata;while(!TI);TI = 0;
}void SendString(char *str)
{while(*str != '\0'){SendByte(*str);str++;}
}//M1qian  M2 hou M3 zuo  M4 you
void Uart_Handler() interrupt 4
{static int i = 0;//靜態(tài)變量,被初始化一次char tmp;if(RI)//中斷處理函數(shù)中,對于接收中斷的響應(yīng){RI = 0;//清除接收中斷標(biāo)志位tmp = SBUF;if(tmp == 'M'){i = 0;}buffer[i++] = tmp;//燈控指令if(buffer[0] == 'M'){switch(buffer[1]){case '1':goForward();break;case '2':goBack();break;case '3':goLeft();break;case '4':goRight();break;default:stop();break;}}if(i == 12) {memset(buffer, '\0', SIZE);i = 0;}}}//motor.c
#include "reg52.h"sbit RightCon1A = P3^7;
sbit RightCon1B = P3^3;sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;void goForward()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 1;
}void goRight()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 0;
}void goLeft()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 1;
}void goBack()
{LeftCon1A = 1;LeftCon1B = 0;RightCon1A = 1;RightCon1B = 0;
}void stop()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 0;
}//time.c
#include "motor.h"
#include "reg52.h"extern unsigned int speedCnt;
unsigned int speed;
char signal = 0;
unsigned int cnt = 0;void Time0Init()
{//1. 配置定時器0工作模式位16位計時TMOD = 0x01;//2. 給初值,定一個0.5出來TL0=0x33;TH0=0xFE;//3. 開始計時TR0 = 1;TF0 = 0;//4. 打開定時器0中斷ET0 = 1;//5. 打開總中斷EAEA = 1;
}void Time0Handler() interrupt 1
{cnt++;  //統(tǒng)計爆表的次數(shù). cnt=1的時候,報表了1//重新給初值TL0=0x33;TH0=0xFE;if(cnt == 2000){//爆表2000次,經(jīng)過了1ssignal = 1;cnt = 0;  //當(dāng)100次表示1s,重新讓cnt從0開始,計算下一次的1s//計算小車的速度,也就是拿到speedCnt的值speed = speedCnt;speedCnt = 0;//1秒后拿到speedCnt個格子,就能算出這1s的速度,格子清零}}

4.4 小車速度顯示在OLED屏

使用oled模塊

//main.c
#include "reg52.h"
#include "intrins.h"
#include "Oled.h"void main()
{//1. OLED初始化Oled_Init();Oled_Clear();Oled_Show_Str(2,2,"speed:35cm/s");while(1);
}//oled.c
#include "reg52.h"
#include "intrins.h"
#include "Oledfont.h"sbit scl = P1^2;
sbit sda = P1^3;void IIC_Start()
{scl = 0;sda = 1;scl = 1;_nop_();sda = 0;_nop_();
}void IIC_Stop()
{scl = 0;sda = 0;scl = 1;_nop_();sda = 1;_nop_();
}char IIC_ACK()
{char flag;sda = 1;//就在時鐘脈沖9期間釋放數(shù)據(jù)線_nop_();scl = 1;_nop_();flag = sda;_nop_();scl = 0;_nop_();return flag;
}void IIC_Send_Byte(char dataSend)
{int i;for(i = 0;i<8;i++){scl = 0;//scl拉低,讓sda做好數(shù)據(jù)準(zhǔn)備sda = dataSend & 0x80;//1000 0000獲得dataSend的最高位,給sda_nop_();//發(fā)送數(shù)據(jù)建立時間scl = 1;//scl拉高開始發(fā)送_nop_();//數(shù)據(jù)發(fā)送時間scl = 0;//發(fā)送完畢拉低_nop_();//dataSend = dataSend << 1;}
}void Oled_Write_Cmd(char dataCmd)
{//	1. start()IIC_Start();//		//	2. 寫入從機地址  b0111 1000 0x78IIC_Send_Byte(0x78);//	3. ACKIIC_ACK();//	4. cotrol byte: (0)(0)000000 寫入命令   (0)(1)000000寫入數(shù)據(jù)IIC_Send_Byte(0x00);//	5. ACKIIC_ACK();//6. 寫入指令/數(shù)據(jù)IIC_Send_Byte(dataCmd);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Write_Data(char dataData)
{//	1. start()IIC_Start();//		//	2. 寫入從機地址  b0111 1000 0x78IIC_Send_Byte(0x78);//	3. ACKIIC_ACK();//	4. cotrol byte: (0)(0)000000 寫入命令   (0)(1)000000寫入數(shù)據(jù)IIC_Send_Byte(0x40);//	5. ACKIIC_ACK();///6. 寫入指令/數(shù)據(jù)IIC_Send_Byte(dataData);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Init(void){Oled_Write_Cmd(0xAE);//--display offOled_Write_Cmd(0x00);//---set low column addressOled_Write_Cmd(0x10);//---set high column addressOled_Write_Cmd(0x40);//--set start line address  Oled_Write_Cmd(0xB0);//--set page addressOled_Write_Cmd(0x81); // contract controlOled_Write_Cmd(0xFF);//--128   Oled_Write_Cmd(0xA1);//set segment remap Oled_Write_Cmd(0xA6);//--normal / reverseOled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)Oled_Write_Cmd(0x3F);//--1/32 dutyOled_Write_Cmd(0xC8);//Com scan directionOled_Write_Cmd(0xD3);//-set display offsetOled_Write_Cmd(0x00);//Oled_Write_Cmd(0xD5);//set osc divisionOled_Write_Cmd(0x80);//Oled_Write_Cmd(0xD8);//set area color mode offOled_Write_Cmd(0x05);//Oled_Write_Cmd(0xD9);//Set Pre-Charge PeriodOled_Write_Cmd(0xF1);//Oled_Write_Cmd(0xDA);//set com pin configuartionOled_Write_Cmd(0x12);//Oled_Write_Cmd(0xDB);//set VcomhOled_Write_Cmd(0x30);//Oled_Write_Cmd(0x8D);//set charge pump enableOled_Write_Cmd(0x14);//Oled_Write_Cmd(0xAF);//--turn on oled panel		
}void Oled_Clear()
{unsigned char i,j; //-128 --- 127for(i=0;i<8;i++){Oled_Write_Cmd(0xB0 + i);//page0--page7//每個page從0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//0到127列,依次寫入0,每寫入數(shù)據(jù),列地址自動偏移for(j = 0;j<128;j++){Oled_Write_Data(0);}}
}void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2unsigned int  i;Oled_Write_Cmd(0xb0+(row*2-2));                           //page 0Oled_Write_Cmd(0x00+(col&0x0f));                          //lowOled_Write_Cmd(0x10+(col>>4));                            //high	for(i=((oledChar-32)*16);i<((oledChar-32)*16+8);i++){Oled_Write_Data(F8X16[i]);                            //寫數(shù)據(jù)oledTable1}Oled_Write_Cmd(0xb0+(row*2-1));                           //page 1Oled_Write_Cmd(0x00+(col&0x0f));                          //lowOled_Write_Cmd(0x10+(col>>4));                            //highfor(i=((oledChar-32)*16+8);i<((oledChar-32)*16+8+8);i++){Oled_Write_Data(F8X16[i]);                            //寫數(shù)據(jù)oledTable1}		
}/******************************************************************************/
// 函數(shù)名稱:Oled_Show_Char 
// 輸入?yún)?shù):oledChar 
// 輸出參數(shù):無 
// 函數(shù)功能:OLED顯示單個字符
/******************************************************************************/
void Oled_Show_Str(char row,char col,char *str){while(*str!=0){Oled_Show_Char(row,col,*str);str++;col += 8;	}		
}

5.遠(yuǎn)程控制小車

5.1 藍(lán)牙控制小車

  • 使用藍(lán)牙模塊,串口透傳
  • 藍(lán)牙模塊,又叫做藍(lán)牙串口模塊

串口透傳技術(shù):

  • 透傳即透明傳送,是指在數(shù)據(jù)的傳輸過程中,通過無線的方式這組數(shù)據(jù)不發(fā)生任何形式的改變,仿 佛傳輸過程是透明的一樣,同時保證傳輸?shù)馁|(zhì)量,原封不動地到了最終接收者手里。
  • 以太網(wǎng),藍(lán)牙,Zigbee, GPRS 等模塊玩法一樣,對嵌入式程序員來說,不需要關(guān)心通訊模塊內(nèi)部數(shù)據(jù) 及協(xié)議棧工作原理,只要通過串口編程獲得數(shù)據(jù)即可

代碼實現(xiàn):

//main.c
#include "motor.h"
#include "delay.h"
#include "uart.h"void main()
{UartInit();while(1){stop();}
}//uart.c
#include "reg52.h"
#include "motor.h"
#include "string.h"
#include "delay.h"
sbit D5 = P3^7;
#define SIZE 12sfr AUXR = 0x8E;
char buffer[SIZE];void UartInit(void)		//9600bps@11.0592MHz
{AUXR = 0x01;SCON = 0x50; //配置串口工作方式1,REN使能接收TMOD &= 0x0F;TMOD |= 0x20;//定時器1工作方式位8位自動重裝TH1 = 0xFD;TL1 = 0xFD;//9600波特率的初值TR1 = 1;//啟動定時器EA = 1;//開啟總中斷ES = 1;//開啟串口中斷
}//M1qian  M2 hou M3 zuo  M4 you
void Uart_Handler() interrupt 4
{static int i = 0;//靜態(tài)變量,被初始化一次char tmp;if(RI)//中斷處理函數(shù)中,對于接收中斷的響應(yīng){RI = 0;//清除接收中斷標(biāo)志位tmp = SBUF;if(tmp == 'M'){i = 0;}buffer[i++] = tmp;//燈控指令if(buffer[0] == 'M'){switch(buffer[1]){case '1':goForward();Delay10ms();break;case '2':goBack();Delay10ms();break;case '3':goLeft();Delay10ms();break;case '4':goRight();Delay10ms();break;default:stop();break;}}if(i == 12) {memset(buffer, '\0', SIZE);i = 0;}}}//motor.c
#include "reg52.h"sbit RightCon1A = P3^2;
sbit RightCon1B = P3^3;sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;void goForward()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 1;
}void goRight()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 0;
}void goLeft()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 1;
}void goBack()
{LeftCon1A = 1;LeftCon1B = 0;RightCon1A = 1;RightCon1B = 0;
}void stop()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 0;
}//delay.c#include "intrins.h"void Delay10ms()		//@11.0592MHz
{unsigned char i, j;i = 18;j = 235;do{while (--j);} while (--i);
}void Delay1000ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}

5.2 藍(lán)牙控制并測速小車

原理:運用上面講到的藍(lán)牙模塊和測速模塊

代碼實現(xiàn):

//main.c
#include "motor.h"
#include "delay.h"
#include "uart.h"
#include "reg52.h"
#include "time.h"
#include "stdio.h"
#include "Oled.h"sbit speedIO = P3^2;//外部中斷0
unsigned int speedCnt = 0; //統(tǒng)計格子,脈沖次數(shù)
extern unsigned int speed;//速度
extern char signal; //主程序發(fā)速度數(shù)據(jù)的通知
char speedMes[24];  //主程序發(fā)送速度數(shù)據(jù)的字符串緩沖區(qū)void Ex0Init()
{EX0 = 1;//允許中斷//EA = 1;在串口初始化函數(shù)中已經(jīng)打開了總中斷IT0 = 1;//外部中斷的下降沿觸發(fā)
}void main()
{Time0Init();//定時器0初始化UartInit();//串口相關(guān)初始化//外部中斷初始化Ex0Init();Oled_Init();Oled_Clear();while(1){if(signal){//定時器1s到點,把signal置一,主程序發(fā)送速度sprintf(speedMes,"speed:%d cm/s",speed);//串口數(shù)據(jù)的字符串拼裝,speed是格子,每個格子1cmSendString(speedMes);//速度發(fā)出去signal = 0;//清0speed,下次由定時器1s后的中斷處理中再置一}Oled_Show_Str(2,2,speedMes);}
}void speedHandler() interrupt 0 //外部中斷處理函數(shù)
{speedCnt++;//碼盤轉(zhuǎn)動了一個格子
}//uart.c
#include "reg52.h"
#include "motor.h"
#include "string.h"
sbit D5 = P3^7;
#define SIZE 12sfr AUXR = 0x8E;
char buffer[SIZE];void UartInit(void)		//9600bps@11.0592MHz
{AUXR = 0x01;SCON = 0x50; //配置串口工作方式1,REN使能接收TMOD &= 0x0F;TMOD |= 0x20;//定時器1工作方式位8位自動重裝TH1 = 0xFD;TL1 = 0xFD;//9600波特率的初值TR1 = 1;//啟動定時器EA = 1;//開啟總中斷ES = 1;//開啟串口中斷
}void SendByte(char mydata)
{SBUF = mydata;while(!TI);TI = 0;
}void SendString(char *str)
{while(*str != '\0'){SendByte(*str);str++;}
}//M1qian  M2 hou M3 zuo  M4 you
void Uart_Handler() interrupt 4
{static int i = 0;//靜態(tài)變量,被初始化一次char tmp;if(RI)//中斷處理函數(shù)中,對于接收中斷的響應(yīng){RI = 0;//清除接收中斷標(biāo)志位tmp = SBUF;if(tmp == 'M'){i = 0;}buffer[i++] = tmp;//燈控指令if(buffer[0] == 'M'){switch(buffer[1]){case '1':goForward();break;case '2':goBack();break;case '3':goLeft();break;case '4':goRight();break;default:stop();break;}}if(i == 12) {memset(buffer, '\0', SIZE);i = 0;}}}//motor.c
#include "reg52.h"sbit RightCon1A = P3^7;
sbit RightCon1B = P3^3;sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;void goForward()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 1;
}void goRight()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 0;
}void goLeft()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 1;
}void goBack()
{LeftCon1A = 1;LeftCon1B = 0;RightCon1A = 1;RightCon1B = 0;
}void stop()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 0;
}//time.c
#include "motor.h"
#include "reg52.h"extern unsigned int speedCnt;
unsigned int speed;
char signal = 0;
unsigned int cnt = 0;void Time0Init()
{//1. 配置定時器0工作模式位16位計時TMOD = 0x01;//2. 給初值,定一個0.5出來TL0=0x33;TH0=0xFE;//3. 開始計時TR0 = 1;TF0 = 0;//4. 打開定時器0中斷ET0 = 1;//5. 打開總中斷EAEA = 1;
}void Time0Handler() interrupt 1
{cnt++;  //統(tǒng)計爆表的次數(shù). cnt=1的時候,報表了1//重新給初值TL0=0x33;TH0=0xFE;if(cnt == 2000){//爆表2000次,經(jīng)過了1ssignal = 1;cnt = 0;  //當(dāng)100次表示1s,重新讓cnt從0開始,計算下一次的1s//計算小車的速度,也就是拿到speedCnt的值speed = speedCnt;speedCnt = 0;//1秒后拿到speedCnt個格子,就能算出這1s的速度,格子清零}}//oled.c
#include "reg52.h"
#include "intrins.h"
#include "Oledfont.h"sbit scl = P1^2;
sbit sda = P1^3;void IIC_Start()
{scl = 0;sda = 1;scl = 1;_nop_();sda = 0;_nop_();
}void IIC_Stop()
{scl = 0;sda = 0;scl = 1;_nop_();sda = 1;_nop_();
}char IIC_ACK()
{char flag;sda = 1;//就在時鐘脈沖9期間釋放數(shù)據(jù)線_nop_();scl = 1;_nop_();flag = sda;_nop_();scl = 0;_nop_();return flag;
}void IIC_Send_Byte(char dataSend)
{int i;for(i = 0;i<8;i++){scl = 0;//scl拉低,讓sda做好數(shù)據(jù)準(zhǔn)備sda = dataSend & 0x80;//1000 0000獲得dataSend的最高位,給sda_nop_();//發(fā)送數(shù)據(jù)建立時間scl = 1;//scl拉高開始發(fā)送_nop_();//數(shù)據(jù)發(fā)送時間scl = 0;//發(fā)送完畢拉低_nop_();//dataSend = dataSend << 1;}
}void Oled_Write_Cmd(char dataCmd)
{//	1. start()IIC_Start();//		//	2. 寫入從機地址  b0111 1000 0x78IIC_Send_Byte(0x78);//	3. ACKIIC_ACK();//	4. cotrol byte: (0)(0)000000 寫入命令   (0)(1)000000寫入數(shù)據(jù)IIC_Send_Byte(0x00);//	5. ACKIIC_ACK();//6. 寫入指令/數(shù)據(jù)IIC_Send_Byte(dataCmd);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Write_Data(char dataData)
{//	1. start()IIC_Start();//		//	2. 寫入從機地址  b0111 1000 0x78IIC_Send_Byte(0x78);//	3. ACKIIC_ACK();//	4. cotrol byte: (0)(0)000000 寫入命令   (0)(1)000000寫入數(shù)據(jù)IIC_Send_Byte(0x40);//	5. ACKIIC_ACK();///6. 寫入指令/數(shù)據(jù)IIC_Send_Byte(dataData);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Init(void){Oled_Write_Cmd(0xAE);//--display offOled_Write_Cmd(0x00);//---set low column addressOled_Write_Cmd(0x10);//---set high column addressOled_Write_Cmd(0x40);//--set start line address  Oled_Write_Cmd(0xB0);//--set page addressOled_Write_Cmd(0x81); // contract controlOled_Write_Cmd(0xFF);//--128   Oled_Write_Cmd(0xA1);//set segment remap Oled_Write_Cmd(0xA6);//--normal / reverseOled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)Oled_Write_Cmd(0x3F);//--1/32 dutyOled_Write_Cmd(0xC8);//Com scan directionOled_Write_Cmd(0xD3);//-set display offsetOled_Write_Cmd(0x00);//Oled_Write_Cmd(0xD5);//set osc divisionOled_Write_Cmd(0x80);//Oled_Write_Cmd(0xD8);//set area color mode offOled_Write_Cmd(0x05);//Oled_Write_Cmd(0xD9);//Set Pre-Charge PeriodOled_Write_Cmd(0xF1);//Oled_Write_Cmd(0xDA);//set com pin configuartionOled_Write_Cmd(0x12);//Oled_Write_Cmd(0xDB);//set VcomhOled_Write_Cmd(0x30);//Oled_Write_Cmd(0x8D);//set charge pump enableOled_Write_Cmd(0x14);//Oled_Write_Cmd(0xAF);//--turn on oled panel		
}void Oled_Clear()
{unsigned char i,j; //-128 --- 127for(i=0;i<8;i++){Oled_Write_Cmd(0xB0 + i);//page0--page7//每個page從0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//0到127列,依次寫入0,每寫入數(shù)據(jù),列地址自動偏移for(j = 0;j<128;j++){Oled_Write_Data(0);}}
}void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2unsigned int  i;Oled_Write_Cmd(0xb0+(row*2-2));                           //page 0Oled_Write_Cmd(0x00+(col&0x0f));                          //lowOled_Write_Cmd(0x10+(col>>4));                            //high	for(i=((oledChar-32)*16);i<((oledChar-32)*16+8);i++){Oled_Write_Data(F8X16[i]);                            //寫數(shù)據(jù)oledTable1}Oled_Write_Cmd(0xb0+(row*2-1));                           //page 1Oled_Write_Cmd(0x00+(col&0x0f));                          //lowOled_Write_Cmd(0x10+(col>>4));                            //highfor(i=((oledChar-32)*16+8);i<((oledChar-32)*16+8+8);i++){Oled_Write_Data(F8X16[i]);                            //寫數(shù)據(jù)oledTable1}		
}/******************************************************************************/
// 函數(shù)名稱:Oled_Show_Char 
// 輸入?yún)?shù):oledChar 
// 輸出參數(shù):無 
// 函數(shù)功能:OLED顯示單個字符
/******************************************************************************/
void Oled_Show_Str(char row,char col,char *str){while(*str!=0){Oled_Show_Char(row,col,*str);str++;col += 8;	}		
}

5.3 wifi控制測速小車

  • Wifi模塊-ESP-01s
  • 藍(lán)牙,ESP-01s,Zigbee, NB-Iot等通信模塊都是基于AT指令的設(shè)計

AT指令介紹:

  • AT指令集是從終端設(shè)備(Terminal Equipment,TE)或數(shù)據(jù)終端設(shè)備(Data Terminal Equipment,DTE)向終端適配器(Terminal Adapter,TA)或數(shù)據(jù)電路終端設(shè)備(Data Circuit Terminal Equipment,DCE)發(fā)送的。
  • 其對所傳輸?shù)臄?shù)據(jù)包大小有定義:即對于AT指令的發(fā)送,除AT兩個字符外,最多可以接收1056個 字符的長度(包括最后的空字符)。
  • 每個AT命令行中只能包含一條AT指令;對于由終端設(shè)備主動向PC端報告的URC指示或者response 響應(yīng),也要求一行最多有一個,不允許上報的一行中有多條指示或者響應(yīng)。AT指令以回車作為結(jié) 尾,響應(yīng)或上報以回車換行為結(jié)尾。

代碼實現(xiàn):

//main.c
#include "motor.h"
#include "delay.h"
#include "uart.h"
#include "reg52.h"
#include "time.h"
#include "stdio.h"
#include "Oled.h"
#include "esp8266.h"sbit speedIO = P3^2;//外部中斷0
unsigned int speedCnt = 0; //統(tǒng)計格子,脈沖次數(shù)
extern unsigned int speed;//速度
extern char signal; //主程序發(fā)速度數(shù)據(jù)的通知
char speedMes[24];  //主程序發(fā)送速度數(shù)據(jù)的字符串緩沖區(qū)
//發(fā)送數(shù)據(jù)
char FSSJ[] = "AT+CIPSEND=0,5\r\n";void Ex0Init()
{EX0 = 1;//允許中斷//EA = 1;在串口初始化函數(shù)中已經(jīng)打開了總中斷IT0 = 1;//外部中斷的下降沿觸發(fā)
}void main()
{Time0Init();//定時器0初始化UartInit();//串口相關(guān)初始化Delay1000ms();//給espwifi模塊上電時間initWifi_AP(); //初始化wifi工作在ap模式waitConnect(); //等待客戶端的連接//外部中斷初始化Ex0Init();Oled_Init();Oled_Clear();while(1){if(signal){//定時器1s到點,把signal置一,主程序發(fā)送速度SendString(FSSJ);Delay1000ms();sprintf(speedMes,"%dcms",speed);//串口數(shù)據(jù)的字符串拼裝,speed是格子,每個格子1cmSendString(speedMes);//速度發(fā)出去signal = 0;//清0speed,下次由定時器1s后的中斷處理中再置一}Oled_Show_Str(2,2,speedMes);}
}void speedHandler() interrupt 0 //外部中斷處理函數(shù)
{speedCnt++;//碼盤轉(zhuǎn)動了一個格子
}//uart.c
#include "reg52.h"
#include "motor.h"
#include "string.h"
sbit D5 = P3^7;
#define SIZE 12sfr AUXR = 0x8E;
char buffer[SIZE];extern char AT_OK_Flag;				//OK返回值的標(biāo)志位
extern char Client_Connect_Flag;void UartInit(void)		//9600bps@11.0592MHz
{AUXR = 0x01;SCON = 0x50; //配置串口工作方式1,REN使能接收TMOD &= 0x0F;TMOD |= 0x20;//定時器1工作方式位8位自動重裝TH1 = 0xFD;TL1 = 0xFD;//9600波特率的初值TR1 = 1;//啟動定時器EA = 1;//開啟總中斷ES = 1;//開啟串口中斷
}void SendByte(char mydata)
{SBUF = mydata;while(!TI);TI = 0;
}void SendString(char *str)
{while(*str != '\0'){SendByte(*str);str++;}
}//M1qian  M2 hou M3 zuo  M4 you
void Uart_Handler() interrupt 4
{static int i = 0;//靜態(tài)變量,被初始化一次char tmp;if(RI)//中斷處理函數(shù)中,對于接收中斷的響應(yīng){RI = 0;//清除接收中斷標(biāo)志位tmp = SBUF;if(tmp == 'M' || tmp == 'O' || tmp == '0'){i = 0;}buffer[i++] = tmp;//連接服務(wù)器等OK返回值指令的判斷if(buffer[0] == 'O' && buffer[1] == 'K'){AT_OK_Flag	= 1;memset(buffer, '\0', SIZE);}if(buffer[0] == '0' && buffer[2] == 'C'){Client_Connect_Flag	= 1;memset(buffer, '\0', SIZE);}//燈控指令if(buffer[0] == 'M'){switch(buffer[1]){case '1':goForward();break;case '2':goBack();break;case '3':goLeft();break;case '4':goRight();break;default:stop();break;}}if(i == 12) {memset(buffer, '\0', SIZE);i = 0;}}}//motor.c
#include "reg52.h"sbit RightCon1A = P3^7;
sbit RightCon1B = P3^3;sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;void goForward()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 1;
}void goRight()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 0;
}void goLeft()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 1;
}void goBack()
{LeftCon1A = 1;LeftCon1B = 0;RightCon1A = 1;RightCon1B = 0;
}void stop()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 0;
}//time.c
#include "motor.h"
#include "reg52.h"extern unsigned int speedCnt;
unsigned int speed;
char signal = 0;
unsigned int cnt = 0;void Time0Init()
{//1. 配置定時器0工作模式位16位計時TMOD = 0x01;//2. 給初值,定一個0.5出來TL0=0x33;TH0=0xFE;//3. 開始計時TR0 = 1;TF0 = 0;//4. 打開定時器0中斷ET0 = 1;//5. 打開總中斷EAEA = 1;
}void Time0Handler() interrupt 1
{cnt++;  //統(tǒng)計爆表的次數(shù). cnt=1的時候,報表了1//重新給初值TL0=0x33;TH0=0xFE;if(cnt == 2000){//爆表2000次,經(jīng)過了1ssignal = 1;cnt = 0;  //當(dāng)100次表示1s,重新讓cnt從0開始,計算下一次的1s//計算小車的速度,也就是拿到speedCnt的值speed = speedCnt;speedCnt = 0;//1秒后拿到speedCnt個格子,就能算出這1s的速度,格子清零}}//oled.c
#include "reg52.h"
#include "intrins.h"
#include "Oledfont.h"sbit scl = P1^2;
sbit sda = P1^3;void IIC_Start()
{scl = 0;sda = 1;scl = 1;_nop_();sda = 0;_nop_();
}void IIC_Stop()
{scl = 0;sda = 0;scl = 1;_nop_();sda = 1;_nop_();
}char IIC_ACK()
{char flag;sda = 1;//就在時鐘脈沖9期間釋放數(shù)據(jù)線_nop_();scl = 1;_nop_();flag = sda;_nop_();scl = 0;_nop_();return flag;
}void IIC_Send_Byte(char dataSend)
{int i;for(i = 0;i<8;i++){scl = 0;//scl拉低,讓sda做好數(shù)據(jù)準(zhǔn)備sda = dataSend & 0x80;//1000 0000獲得dataSend的最高位,給sda_nop_();//發(fā)送數(shù)據(jù)建立時間scl = 1;//scl拉高開始發(fā)送_nop_();//數(shù)據(jù)發(fā)送時間scl = 0;//發(fā)送完畢拉低_nop_();//dataSend = dataSend << 1;}
}void Oled_Write_Cmd(char dataCmd)
{//	1. start()IIC_Start();//		//	2. 寫入從機地址  b0111 1000 0x78IIC_Send_Byte(0x78);//	3. ACKIIC_ACK();//	4. cotrol byte: (0)(0)000000 寫入命令   (0)(1)000000寫入數(shù)據(jù)IIC_Send_Byte(0x00);//	5. ACKIIC_ACK();//6. 寫入指令/數(shù)據(jù)IIC_Send_Byte(dataCmd);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Write_Data(char dataData)
{//	1. start()IIC_Start();//		//	2. 寫入從機地址  b0111 1000 0x78IIC_Send_Byte(0x78);//	3. ACKIIC_ACK();//	4. cotrol byte: (0)(0)000000 寫入命令   (0)(1)000000寫入數(shù)據(jù)IIC_Send_Byte(0x40);//	5. ACKIIC_ACK();///6. 寫入指令/數(shù)據(jù)IIC_Send_Byte(dataData);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Init(void){Oled_Write_Cmd(0xAE);//--display offOled_Write_Cmd(0x00);//---set low column addressOled_Write_Cmd(0x10);//---set high column addressOled_Write_Cmd(0x40);//--set start line address  Oled_Write_Cmd(0xB0);//--set page addressOled_Write_Cmd(0x81); // contract controlOled_Write_Cmd(0xFF);//--128   Oled_Write_Cmd(0xA1);//set segment remap Oled_Write_Cmd(0xA6);//--normal / reverseOled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)Oled_Write_Cmd(0x3F);//--1/32 dutyOled_Write_Cmd(0xC8);//Com scan directionOled_Write_Cmd(0xD3);//-set display offsetOled_Write_Cmd(0x00);//Oled_Write_Cmd(0xD5);//set osc divisionOled_Write_Cmd(0x80);//Oled_Write_Cmd(0xD8);//set area color mode offOled_Write_Cmd(0x05);//Oled_Write_Cmd(0xD9);//Set Pre-Charge PeriodOled_Write_Cmd(0xF1);//Oled_Write_Cmd(0xDA);//set com pin configuartionOled_Write_Cmd(0x12);//Oled_Write_Cmd(0xDB);//set VcomhOled_Write_Cmd(0x30);//Oled_Write_Cmd(0x8D);//set charge pump enableOled_Write_Cmd(0x14);//Oled_Write_Cmd(0xAF);//--turn on oled panel		
}void Oled_Clear()
{unsigned char i,j; //-128 --- 127for(i=0;i<8;i++){Oled_Write_Cmd(0xB0 + i);//page0--page7//每個page從0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//0到127列,依次寫入0,每寫入數(shù)據(jù),列地址自動偏移for(j = 0;j<128;j++){Oled_Write_Data(0);}}
}void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2unsigned int  i;Oled_Write_Cmd(0xb0+(row*2-2));                           //page 0Oled_Write_Cmd(0x00+(col&0x0f));                          //lowOled_Write_Cmd(0x10+(col>>4));                            //high	for(i=((oledChar-32)*16);i<((oledChar-32)*16+8);i++){Oled_Write_Data(F8X16[i]);                            //寫數(shù)據(jù)oledTable1}Oled_Write_Cmd(0xb0+(row*2-1));                           //page 1Oled_Write_Cmd(0x00+(col&0x0f));                          //lowOled_Write_Cmd(0x10+(col>>4));                            //highfor(i=((oledChar-32)*16+8);i<((oledChar-32)*16+8+8);i++){Oled_Write_Data(F8X16[i]);                            //寫數(shù)據(jù)oledTable1}		
}/******************************************************************************/
// 函數(shù)名稱:Oled_Show_Char 
// 輸入?yún)?shù):oledChar 
// 輸出參數(shù):無 
// 函數(shù)功能:OLED顯示單個字符
/******************************************************************************/
void Oled_Show_Str(char row,char col,char *str){while(*str!=0){Oled_Show_Char(row,col,*str);str++;col += 8;	}		
}//esp8266.c
#include "uart.h"//1 工作在路由模式
code char LYMO[] = "AT+CWMODE=2\r\n";
//2 使能多鏈接
code char DLJ[] = "AT+CIPMUX=1\r\n"; 
//3 建立TCPServer
code char JLFW[] = "AT+CIPSERVER=1\r\n"; // default port = 333 char AT_OK_Flag = 0;				//OK返回值的標(biāo)志位
char Client_Connect_Flag = 0;void initWifi_AP()
{SendString(LYMO);while(!AT_OK_Flag);AT_OK_Flag = 0;SendString(DLJ);while(!AT_OK_Flag);AT_OK_Flag = 0;
}void waitConnect()
{SendString(JLFW);while(!Client_Connect_Flag);AT_OK_Flag = 0;	
}//delay.c
#include "intrins.h"void Delay1000ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}

5.4 4g控制小車

原理:運用EC03-DNC4G通信模塊

模塊介紹:

  • 基于串口AT指令的開發(fā)方式
  • 有兩種工作模式,默認(rèn)是透傳模式,通過其他方式進(jìn)入AT指令模式
  • 注意插卡不要出錯,下圖紅色位置為SIM卡狀態(tài)燈,亮才是正常

代碼不做修改,直接基于藍(lán)牙小車整合,?4g模塊只要做好外網(wǎng)透傳就可以了

6.語音控制小車

6.1語音模塊配置

使用SU-03T / LD3320

具體介紹看我之前寫過的博客:https://blog.csdn.net/m0_74712453/article/details/13171085

6.2 語音控制小車開發(fā)和調(diào)試代碼

代碼示例:

//main.c
#include "reg52.h"
#include "hc04.h"
#include "delay.h"
#include "sg90.h"
#include "Oled.h"
#include "motor.h"#define MIDDLE 0
#define LEFT 1
#define RIGHT 2#define BZ 1
#define XJ 2
#define GS 3sbit A25 = P1^5;
sbit A26 = P1^6;
sbit A27 = P1^7;sbit leftSensorX = P2^7;
sbit rightSensorX = P2^6;sbit leftSensorG = P2^5;
sbit rightSensorG = P2^4;char dir;double disMiddle;
double disLeft;
double disRight;void xunjiMode()
{if(leftSensorX == 0 && rightSensorX == 0){goForward();}if(leftSensorX == 1 && rightSensorX == 0){goLeft();}if(leftSensorX == 0 && rightSensorX == 1){goRight();}if(leftSensorX == 1 && rightSensorX == 1){//停stop();}
}void gensuiMode()
{if(leftSensorG == 0 && rightSensorG == 0){goForward();}if(leftSensorG == 1 && rightSensorG == 0){goRight();}if(leftSensorG == 0 && rightSensorG == 1){goLeft();}if(leftSensorG == 1 && rightSensorG == 1){//停stop();}
}void bizhangMode()
{if(dir != MIDDLE){sgMiddle();dir = MIDDLE;Delay300ms();}disMiddle = get_distance();if(disMiddle > 35){//前進(jìn)goForward();}else if(disMiddle < 10){goBack();}else{//停止stop();//測左邊距離sgLeft();Delay300ms();disLeft = get_distance();sgMiddle();Delay300ms();sgRight();dir = RIGHT;Delay300ms();disRight = get_distance();if(disLeft < disRight){goRight();Delay150ms();stop();}if(disRight < disLeft){goLeft();Delay150ms();stop();}}}void main()
{int mark = 0;Time0Init();Time1Init();//舵機的初始位置sgMiddle();Delay300ms();Delay300ms();dir = MIDDLE;Oled_Init();Oled_Clear();Oled_Show_Str(2,2,"-----Ready----");while(1){//滿足尋跡模式的條件if(A25 == 0 && A26 == 1 && A27 == 1){if(mark != XJ){Oled_Clear();Oled_Show_Str(2,2,"-----XunJi----");}mark = XJ;xunjiMode();}//滿足跟隨模式的條件if(A25 == 1 && A26 == 0 && A27 == 1){if(mark != GS){Oled_Clear();Oled_Show_Str(2,2,"-----GenSui----");}mark = GS;gensuiMode();}//滿足避障模式的條件if(A25 == 1 && A26 == 1 && A27 == 0){if(mark != BZ){Oled_Clear();Oled_Show_Str(2,2,"-----BiZhang----");}mark = BZ;bizhangMode();}}
}//hc04.c
#include "reg52.h"
#include "delay.h"sbit Trig     = P2^3;
sbit Echo     = P2^2;void Time1Init()
{	TMOD &= 0x0F;		//設(shè)置定時器模式TMOD |= 0x10;TH1 = 0;TL1 = 0;//設(shè)置定時器0工作模式1,初始值設(shè)定0開始數(shù)數(shù),不著急啟動定時器
}void startHC()
{Trig = 0;Trig = 1;Delay10us();Trig = 0;
}double get_distance()
{double time;//定時器數(shù)據(jù)清零,以便下一次測距TH1 = 0;TL1 = 0;//1. Trig ,給Trig端口至少10us的高電平startHC();//2. echo由低電平跳轉(zhuǎn)到高電平,表示開始發(fā)送波while(Echo == 0);//波發(fā)出去的那一下,開始啟動定時器TR1 = 1;//3. 由高電平跳轉(zhuǎn)回低電平,表示波回來了while(Echo == 1);//波回來的那一下,我們開始停止定時器TR1 = 0;//4. 計算出中間經(jīng)過多少時間time = (TH1 * 256 + TL1)*1.085;//us為單位//5. 距離 = 速度 (340m/s)* 時間/2return  (time * 0.017);
}//delay.c
#include "intrins.h"void Delay2000ms()		//@11.0592MHz
{unsigned char i, j, k;i = 15;j = 2;k = 235;do{do{while (--k);} while (--j);} while (--i);
}void Delay10us()		//@11.0592MHz
{unsigned char i;i = 2;while (--i);
}void Delay300ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 3;j = 26;k = 223;do{do{while (--k);} while (--j);} while (--i);
}void Delay150ms()		//@11.0592MHz
{unsigned char i, j, k;i = 2;j = 13;k = 237;do{do{while (--k);} while (--j);} while (--i);
}void Delay450ms()		//@11.0592MHz
{unsigned char i, j, k;_nop_();i = 4;j = 39;k = 209;do{do{while (--k);} while (--j);} while (--i);
}//sg90.c
#include "reg52.h"
#include "delay.h"sbit sg90_con = P1^1;int jd;
int cnt = 0;void Time0Init()
{//1. 配置定時器0工作模式位16位計時TMOD &= 0xF0;		//設(shè)置定時器模式TMOD |= 0x01;//2. 給初值,定一個0.5出來TL0=0x33;TH0=0xFE;//3. 開始計時TR0 = 1;TF0 = 0;//4. 打開定時器0中斷ET0 = 1;//5. 打開總中斷EAEA = 1;
}void sgMiddle()
{//中間位置jd = 3; //90度 1.5ms高電平cnt = 0;
}void sgLeft()
{//左邊位置jd = 5; //135度 1.5ms高電平cnt = 0;
}void sgRight()
{//右邊位置jd = 1; //0度cnt = 0;
}void Time0Handler() interrupt 1
{cnt++;  //統(tǒng)計爆表的次數(shù). cnt=1的時候,報表了1//重新給初值TL0=0x33;TH0=0xFE;//控制PWM波if(cnt < jd){sg90_con = 1;}else{sg90_con = 0;}if(cnt == 40){//爆表40次,經(jīng)過了20mscnt = 0;  //當(dāng)100次表示1s,重新讓cnt從0開始,計算下一次的1ssg90_con = 1;}}//motor.c
#include "reg52.h"sbit RightCon1A = P3^7;
sbit RightCon1B = P3^3;sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;void goForward()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 1;
}void goRight()
{LeftCon1A = 0;LeftCon1B = 1;RightCon1A = 0;RightCon1B = 0;
}void goLeft()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 1;
}void goBack()
{LeftCon1A = 1;LeftCon1B = 0;RightCon1A = 1;RightCon1B = 0;
}void stop()
{LeftCon1A = 0;LeftCon1B = 0;RightCon1A = 0;RightCon1B = 0;
}//oled.c
#include "reg52.h"
#include "intrins.h"
#include "Oledfont.h"sbit scl = P1^2;
sbit sda = P1^3;void IIC_Start()
{scl = 0;sda = 1;scl = 1;_nop_();sda = 0;_nop_();
}void IIC_Stop()
{scl = 0;sda = 0;scl = 1;_nop_();sda = 1;_nop_();
}char IIC_ACK()
{char flag;sda = 1;//就在時鐘脈沖9期間釋放數(shù)據(jù)線_nop_();scl = 1;_nop_();flag = sda;_nop_();scl = 0;_nop_();return flag;
}void IIC_Send_Byte(char dataSend)
{int i;for(i = 0;i<8;i++){scl = 0;//scl拉低,讓sda做好數(shù)據(jù)準(zhǔn)備sda = dataSend & 0x80;//1000 0000獲得dataSend的最高位,給sda_nop_();//發(fā)送數(shù)據(jù)建立時間scl = 1;//scl拉高開始發(fā)送_nop_();//數(shù)據(jù)發(fā)送時間scl = 0;//發(fā)送完畢拉低_nop_();//dataSend = dataSend << 1;}
}void Oled_Write_Cmd(char dataCmd)
{//	1. start()IIC_Start();//		//	2. 寫入從機地址  b0111 1000 0x78IIC_Send_Byte(0x78);//	3. ACKIIC_ACK();//	4. cotrol byte: (0)(0)000000 寫入命令   (0)(1)000000寫入數(shù)據(jù)IIC_Send_Byte(0x00);//	5. ACKIIC_ACK();//6. 寫入指令/數(shù)據(jù)IIC_Send_Byte(dataCmd);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Write_Data(char dataData)
{//	1. start()IIC_Start();//		//	2. 寫入從機地址  b0111 1000 0x78IIC_Send_Byte(0x78);//	3. ACKIIC_ACK();//	4. cotrol byte: (0)(0)000000 寫入命令   (0)(1)000000寫入數(shù)據(jù)IIC_Send_Byte(0x40);//	5. ACKIIC_ACK();///6. 寫入指令/數(shù)據(jù)IIC_Send_Byte(dataData);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Init(void){Oled_Write_Cmd(0xAE);//--display offOled_Write_Cmd(0x00);//---set low column addressOled_Write_Cmd(0x10);//---set high column addressOled_Write_Cmd(0x40);//--set start line address  Oled_Write_Cmd(0xB0);//--set page addressOled_Write_Cmd(0x81); // contract controlOled_Write_Cmd(0xFF);//--128   Oled_Write_Cmd(0xA1);//set segment remap Oled_Write_Cmd(0xA6);//--normal / reverseOled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)Oled_Write_Cmd(0x3F);//--1/32 dutyOled_Write_Cmd(0xC8);//Com scan directionOled_Write_Cmd(0xD3);//-set display offsetOled_Write_Cmd(0x00);//Oled_Write_Cmd(0xD5);//set osc divisionOled_Write_Cmd(0x80);//Oled_Write_Cmd(0xD8);//set area color mode offOled_Write_Cmd(0x05);//Oled_Write_Cmd(0xD9);//Set Pre-Charge PeriodOled_Write_Cmd(0xF1);//Oled_Write_Cmd(0xDA);//set com pin configuartionOled_Write_Cmd(0x12);//Oled_Write_Cmd(0xDB);//set VcomhOled_Write_Cmd(0x30);//Oled_Write_Cmd(0x8D);//set charge pump enableOled_Write_Cmd(0x14);//Oled_Write_Cmd(0xAF);//--turn on oled panel		
}void Oled_Clear()
{unsigned char i,j; //-128 --- 127for(i=0;i<8;i++){Oled_Write_Cmd(0xB0 + i);//page0--page7//每個page從0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//0到127列,依次寫入0,每寫入數(shù)據(jù),列地址自動偏移for(j = 0;j<128;j++){Oled_Write_Data(0);}}
}void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2unsigned int  i;Oled_Write_Cmd(0xb0+(row*2-2));                           //page 0Oled_Write_Cmd(0x00+(col&0x0f));                          //lowOled_Write_Cmd(0x10+(col>>4));                            //high	for(i=((oledChar-32)*16);i<((oledChar-32)*16+8);i++){Oled_Write_Data(F8X16[i]);                            //寫數(shù)據(jù)oledTable1}Oled_Write_Cmd(0xb0+(row*2-1));                           //page 1Oled_Write_Cmd(0x00+(col&0x0f));                          //lowOled_Write_Cmd(0x10+(col>>4));                            //highfor(i=((oledChar-32)*16+8);i<((oledChar-32)*16+8+8);i++){Oled_Write_Data(F8X16[i]);                            //寫數(shù)據(jù)oledTable1}		
}/******************************************************************************/
// 函數(shù)名稱:Oled_Show_Char 
// 輸入?yún)?shù):oledChar 
// 輸出參數(shù):無 
// 函數(shù)功能:OLED顯示單個字符
/******************************************************************************/
void Oled_Show_Str(char row,char col,char *str){while(*str!=0){Oled_Show_Char(row,col,*str);str++;col += 8;	}		
}

???????

http://m.aloenet.com.cn/news/28.html

相關(guān)文章:

  • 如何建設(shè)英文網(wǎng)站/淘寶店鋪買賣交易平臺
  • 開一個網(wǎng)站建設(shè)公司/it培訓(xùn)四個月騙局
  • 廊坊市做網(wǎng)站/贛州seo排名
  • 手機商城網(wǎng)站開發(fā)/seo流量的提升的軟件
  • 做澳洲外貿(mào)的網(wǎng)站有哪些/港港網(wǎng)app下載最新版
  • 不懂代碼用cms做網(wǎng)站/h5制作
  • 好的做網(wǎng)站公司/營銷網(wǎng)站做的好的公司
  • 什么做網(wǎng)站/學(xué)生網(wǎng)頁制作成品
  • 福建建筑人才服務(wù)中心檔案/熱狗seo顧問
  • 做網(wǎng)站困難嗎/優(yōu)秀網(wǎng)站設(shè)計欣賞
  • 做貨到付款的購物網(wǎng)站/seo的中文含義是什么
  • 網(wǎng)站后臺是怎樣制作/經(jīng)典軟文案例100例簡短
  • 2021年有沒有人給個網(wǎng)站/全網(wǎng)營銷系統(tǒng)
  • 長江設(shè)計公司/網(wǎng)絡(luò)優(yōu)化報告
  • 萬網(wǎng)網(wǎng)站備案多久/免費優(yōu)化網(wǎng)站
  • 上海網(wǎng)站排名優(yōu)化公司/谷歌seo快速排名軟件首頁
  • 網(wǎng)站建設(shè)開發(fā)平臺/網(wǎng)絡(luò)服務(wù)器的作用
  • 做平面什么網(wǎng)站好用/百度禁止seo推廣
  • 中國平面設(shè)計網(wǎng)站/廣告營銷案例分析
  • 網(wǎng)站建設(shè)橙子/百度教育app
  • 蘇省住房和城鄉(xiāng)建設(shè)廳網(wǎng)站首頁/百度應(yīng)用市場app下載安裝
  • 做網(wǎng)站需要源碼/河南做網(wǎng)站優(yōu)化