有做瀏覽單的網(wǎng)站/百度小說(shuō)風(fēng)云榜2022
目錄
1.電機(jī)模塊開(kāi)發(fā)
1.1 讓小車(chē)動(dòng)起來(lái)
1.2 串口控制小車(chē)方向
1.3 如何進(jìn)行小車(chē)PWM調(diào)速
1.4 PWM方式實(shí)現(xiàn)小車(chē)轉(zhuǎn)向
2.循跡小車(chē)?
2.1 循跡模塊使用
2.2 循跡小車(chē)原理
2.3 循跡小車(chē)核心代碼
3.跟隨/避障小車(chē)
3.1 紅外壁障模塊分析?編輯
3.2 跟隨小車(chē)的原理
3.3 跟隨小車(chē)開(kāi)發(fā)和調(diào)試代碼
3.4 超聲波模塊介紹
3.5 搖頭測(cè)距小車(chē)開(kāi)發(fā)和調(diào)試代碼
4.測(cè)速小車(chē)
4.1 測(cè)速模塊
4.2 測(cè)試原理和單位換算
4.3 定時(shí)器和中斷實(shí)現(xiàn)測(cè)速開(kāi)發(fā)和調(diào)試代碼
4.4 小車(chē)速度顯示在OLED屏
5.遠(yuǎn)程控制小車(chē)
5.1 藍(lán)牙控制小車(chē)
5.2 藍(lán)牙控制并測(cè)速小車(chē)
5.3 wifi控制測(cè)速小車(chē)
5.4 4g控制小車(chē)
6.語(yǔ)音控制小車(chē)
6.1語(yǔ)音模塊配置:
6.2 語(yǔ)音控制小車(chē)開(kāi)發(fā)和調(diào)試代碼
1.電機(jī)模塊開(kāi)發(fā)
L9110s概述
接通VCC,GND 模塊電源指示燈亮, 以下資料來(lái)源官方,具體根據(jù)實(shí)際調(diào)試
IA1輸入高電平,IA1輸入低電平,【OA1 OB1】電機(jī)正轉(zhuǎn);
IA1輸入低電平,IA1輸入高電平,【OA1 OB1】電機(jī)反轉(zhuǎn);
IA2輸入高電平,IA2輸入低電平,【OA2 OB2】電機(jī)正轉(zhuǎn);
IA2輸入低電平,IA2輸入高電平,【OA2 OB2】電機(jī)反轉(zhuǎn);
1.1 讓小車(chē)動(dòng)起來(lái)
核心代碼:
#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 串口控制小車(chē)方向
- 串口分文件編程進(jìn)行代碼整合——具體過(guò)程看課程,主要考驗(yàn)C語(yǔ)言功底和代碼調(diào)試能力,通過(guò)現(xiàn)象來(lái)改代碼
- 接入藍(lán)牙模塊,通過(guò)藍(lán)牙控制小車(chē)
- 添加點(diǎn)動(dòng)控制,如果APP支持按下一直發(fā)數(shù)據(jù),松開(kāi)就停止發(fā)數(shù)據(jù)(藍(lán)牙調(diào)試助手的自定義按鍵不 能實(shí)現(xiàn)),就能實(shí)現(xiàn)前進(jìn)按鍵按下后小車(chē)一直往前走的功能
1.3 如何進(jìn)行小車(chē)PWM調(diào)速
原理: 全速前進(jìn)是LeftCon1A = 0; LeftCon1B = 1;完全停止是LeftCon1A = 0;LeftCon1B = 0;那么單位時(shí) 間內(nèi),比如20ms, 有15ms是全速前進(jìn),5ms是完全停止, 速度就會(huì)比5ms全速前進(jìn),15ms完全停止獲得的功率多,相應(yīng)的速度更快!
開(kāi)發(fā):借用PWM的舵機(jī)控制代碼
核心代碼:
#include "motor.h"
#include "delay.h"
#include "uart.h"
#include "time.h"extern char speed;void main()
{Time0Init();//UartInit();while(1){speed = 10;//10份單位時(shí)間全速運(yùn)行,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. 配置定時(shí)器0工作模式位16位計(jì)時(shí)TMOD = 0x01;//2. 給初值,定一個(gè)0.5出來(lái)TL0=0x33;TH0=0xFE;//3. 開(kāi)始計(jì)時(shí)TR0 = 1;TF0 = 0;//4. 打開(kāi)定時(shí)器0中斷ET0 = 1;//5. 打開(kāi)總中斷EAEA = 1;
}void Time0Handler() interrupt 1
{cnt++; //統(tǒng)計(jì)爆表的次數(shù). cnt=1的時(shí)候,報(bào)表了1//重新給初值TL0=0x33;TH0=0xFE;//控制PWM波if(cnt < speed){//前進(jìn)goForward();}else{//停止stop();}if(cnt == 40){//爆表40次,經(jīng)過(guò)了20mscnt = 0; //當(dāng)100次表示1s,重新讓cnt從0開(kāi)始,計(jì)算下一次的1s}}
1.4 PWM方式實(shí)現(xiàn)小車(chē)轉(zhuǎn)向
原理: 左輪定時(shí)器0調(diào)速,右輪定時(shí)器1調(diào)速,那么左轉(zhuǎn)就是右輪速度大于左輪!
核心代碼:
#include "motor.h"
#include "reg52.h"char speedLeft;
char cntLeft = 0;char speedRight;
char cntRight = 0;void Time1Init()
{//1. 配置定時(shí)器1工作模式位16位計(jì)時(shí)TMOD &= 0x0F;TMOD |= 0x1 << 4;//2. 給初值,定一個(gè)0.5出來(lái)TL1=0x33;TH1=0xFE;//3. 開(kāi)始計(jì)時(shí)TR1 = 1;TF1 = 0;//4. 打開(kāi)定時(shí)器1中斷ET1 = 1;//5. 打開(kāi)總中斷EAEA = 1;
}void Time0Init()
{//1. 配置定時(shí)器0工作模式位16位計(jì)時(shí)TMOD = 0x01;//2. 給初值,定一個(gè)0.5出來(lái)TL0=0x33;TH0=0xFE;//3. 開(kāi)始計(jì)時(shí)TR0 = 1;TF0 = 0;//4. 打開(kāi)定時(shí)器0中斷ET0 = 1;//5. 打開(kāi)總中斷EAEA = 1;
}void Time1Handler() interrupt 3
{cntRight++; //統(tǒng)計(jì)爆表的次數(shù). cnt=1的時(shí)候,報(bào)表了1//重新給初值TL1=0x33;TH1=0xFE;//控制PWM波if(cntRight < speedRight){//右前進(jìn)goForwardRight();}else{//停止stopRight();}if(cntRight == 40){//爆表40次,經(jīng)過(guò)了20mscntRight = 0; //當(dāng)100次表示1s,重新讓cnt從0開(kāi)始,計(jì)算下一次的1s}}void Time0Handler() interrupt 1
{cntLeft++; //統(tǒng)計(jì)爆表的次數(shù). cnt=1的時(shí)候,報(bào)表了1//重新給初值TL0=0x33;TH0=0xFE;//控制PWM波if(cntLeft < speedLeft){//左前進(jìn)goForwardLeft();}else{//停止stopLeft();}if(cntLeft == 40){//爆表40次,經(jīng)過(guò)了20mscntLeft = 0; //當(dāng)100次表示1s,重新讓cnt從0開(kāi)始,計(jì)算下一次的1s}}
2.循跡小車(chē)?
2.1 循跡模塊使用
- TCRT5000傳感器的紅外發(fā)射二極管不斷發(fā)射紅外線
- 當(dāng)發(fā)射出的紅外線沒(méi)有被反射回來(lái)或被反射回來(lái)但強(qiáng)度不夠大時(shí)
- 紅外接收管一直處于關(guān)斷狀態(tài),此時(shí)模塊的輸出端為高電平,指示二極管一直處于熄滅狀態(tài)
- 被檢測(cè)物體出現(xiàn)在檢測(cè)范圍內(nèi)時(shí),紅外線被反射回來(lái)且強(qiáng)度足夠大,紅外接收管飽和
- 此時(shí)模塊的輸出端為低電平,指示二極管被點(diǎn)亮
- 總結(jié)就是一句話,沒(méi)反射回來(lái),D0輸出高電平,滅燈
接線方式
- VCC:接電源正極(3-5V)
- GND:接電源負(fù)極 DO:TTL開(kāi)關(guān)信號(hào)輸出0、1
- AO:模擬信號(hào)輸出(不同距離輸出不同的電壓,此腳一般可以不接)
2.2 循跡小車(chē)原理
由于黑色具有較強(qiáng)的吸收能力,當(dāng)循跡模塊發(fā)射的紅外線照射到黑線時(shí),紅外線將會(huì)被黑線吸收,導(dǎo)致 循跡模塊上光敏三極管處于關(guān)閉狀態(tài),此時(shí)模塊上一個(gè)LED熄滅。在沒(méi)有檢測(cè)到黑線時(shí),模塊上兩個(gè)LED常亮
總結(jié)就是一句話,有感應(yīng)到黑線,D0輸出高電平 ,滅燈
2.3 循跡小車(chē)核心代碼
//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份單位時(shí)間全速運(yùn)行,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. 配置定時(shí)器1工作模式位16位計(jì)時(shí)TMOD &= 0x0F;TMOD |= 0x1 << 4;//2. 給初值,定一個(gè)0.5出來(lái)TL1=0x33;TH1=0xFE;//3. 開(kāi)始計(jì)時(shí)TR1 = 1;TF1 = 0;//4. 打開(kāi)定時(shí)器1中斷ET1 = 1;//5. 打開(kāi)總中斷EAEA = 1;
}void Time0Init()
{//1. 配置定時(shí)器0工作模式位16位計(jì)時(shí)TMOD = 0x01;//2. 給初值,定一個(gè)0.5出來(lái)TL0=0x33;TH0=0xFE;//3. 開(kāi)始計(jì)時(shí)TR0 = 1;TF0 = 0;//4. 打開(kāi)定時(shí)器0中斷ET0 = 1;//5. 打開(kāi)總中斷EAEA = 1;
}void Time1Handler() interrupt 3
{cntRight++; //統(tǒng)計(jì)爆表的次數(shù). cnt=1的時(shí)候,報(bào)表了1//重新給初值TL1=0x33;TH1=0xFE;//控制PWM波if(cntRight < speedRight){//右前進(jìn)goForwardRight();}else{//停止stopRight();}if(cntRight == 40){//爆表40次,經(jīng)過(guò)了20mscntRight = 0; //當(dāng)100次表示1s,重新讓cnt從0開(kāi)始,計(jì)算下一次的1s}}void Time0Handler() interrupt 1
{cntLeft++; //統(tǒng)計(jì)爆表的次數(shù). cnt=1的時(shí)候,報(bào)表了1//重新給初值TL0=0x33;TH0=0xFE;//控制PWM波if(cntLeft < speedLeft){//左前進(jìn)goForwardLeft();}else{//停止stopLeft();}if(cntLeft == 40){//爆表40次,經(jīng)過(guò)了20mscntLeft = 0; //當(dāng)100次表示1s,重新讓cnt從0開(kāi)始,計(jì)算下一次的1s}}
3.跟隨/避障小車(chē)
3.1 紅外壁障模塊分析
原理和循跡是一樣的,循跡紅外觀朝下,跟隨朝前
3.2 跟隨小車(chē)的原理
- 左邊跟隨模塊能返回紅外,輸出低電平,右邊不能返回,輸出高電平,說(shuō)明物體在左邊,需要左轉(zhuǎn)
- 右邊跟隨模塊能返回紅外,輸出低電平,左邊不能返回,輸出高電平,說(shuō)明物體在右邊,需要右轉(zhuǎn)
3.3 跟隨小車(chē)開(kāi)發(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 超聲波模塊介紹
使用超聲波模塊,型號(hào):HC-SR04
- 怎么讓它發(fā)送波 Trig ,給Trig端口至少10us的高電平
- 怎么知道它開(kāi)始發(fā)了 Echo信號(hào),由低電平跳轉(zhuǎn)到高電平,表示開(kāi)始發(fā)送波
- 怎么知道接收了返回波 Echo,由高電平跳轉(zhuǎn)回低電平,表示波回來(lái)了
- 怎么算時(shí)間 Echo引腳維持高電平的時(shí)間! 波發(fā)出去的那一下,開(kāi)始啟動(dòng)定時(shí)器 波回來(lái)的拿一下,我們開(kāi)始停止定時(shí)器,計(jì)算出中間經(jīng)過(guò)多少時(shí)間
- 怎么算距離 距離 = 速度 (340m/s)* 時(shí)間/2
時(shí)序圖:
3.5 搖頭測(cè)距小車(chē)開(kāi)發(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();//舵機(jī)的初始位置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();//測(cè)左邊距離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è)置定時(shí)器模式TMOD |= 0x10;TH1 = 0;TL1 = 0;//設(shè)置定時(shí)器0工作模式1,初始值設(shè)定0開(kāi)始數(shù)數(shù),不著急啟動(dòng)定時(shí)器
}void startHC()
{Trig = 0;Trig = 1;Delay10us();Trig = 0;
}double get_distance()
{double time;//定時(shí)器數(shù)據(jù)清零,以便下一次測(cè)距TH1 = 0;TL1 = 0;//1. Trig ,給Trig端口至少10us的高電平startHC();//2. echo由低電平跳轉(zhuǎn)到高電平,表示開(kāi)始發(fā)送波while(Echo == 0);//波發(fā)出去的那一下,開(kāi)始啟動(dòng)定時(shí)器TR1 = 1;//3. 由高電平跳轉(zhuǎn)回低電平,表示波回來(lái)了while(Echo == 1);//波回來(lái)的那一下,我們開(kāi)始停止定時(shí)器TR1 = 0;//4. 計(jì)算出中間經(jīng)過(guò)多少時(shí)間time = (TH1 * 256 + TL1)*1.085;//us為單位//5. 距離 = 速度 (340m/s)* 時(shí)間/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. 配置定時(shí)器0工作模式位16位計(jì)時(shí)TMOD &= 0xF0; //設(shè)置定時(shí)器模式TMOD |= 0x01;//2. 給初值,定一個(gè)0.5出來(lái)TL0=0x33;TH0=0xFE;//3. 開(kāi)始計(jì)時(shí)TR0 = 1;TF0 = 0;//4. 打開(kāi)定時(shí)器0中斷ET0 = 1;//5. 打開(kāi)總中斷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)計(jì)爆表的次數(shù). cnt=1的時(shí)候,報(bào)表了1//重新給初值TL0=0x33;TH0=0xFE;//控制PWM波if(cnt < jd){sg90_con = 1;}else{sg90_con = 0;}if(cnt == 40){//爆表40次,經(jīng)過(guò)了20mscnt = 0; //當(dāng)100次表示1s,重新讓cnt從0開(kāi)始,計(jì)算下一次的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.測(cè)速小車(chē)
4.1 測(cè)速模塊
- 用途:廣泛用于電機(jī)轉(zhuǎn)速檢測(cè),脈沖計(jì)數(shù),位置限位等。
- 有遮擋,輸出高電平;無(wú)遮擋,輸出低電平
- 接線 :VCC 接電源正極3.3-5V
- GND 接電源負(fù)極 DO TTL開(kāi)關(guān)信號(hào)輸出
- AO 此模塊不起作用
4.2 測(cè)試原理和單位換算
- 輪子走一圈,經(jīng)過(guò)一個(gè)周長(zhǎng),C = 2x3.14x半徑= 3.14 x 直徑(6.5cm)
- 對(duì)應(yīng)的碼盤(pán)也轉(zhuǎn)了一圈,碼盤(pán)有20個(gè)格子,每經(jīng)過(guò)一個(gè)格子,會(huì)遮擋(高電平)和不遮擋(低電平), 那么一個(gè)脈沖就是走了 3.14 * 6.5 cm /20 = 1.0205CM
- 定時(shí)器可以設(shè)計(jì)成一秒,統(tǒng)計(jì)脈沖數(shù),一個(gè)脈沖就是1cm
- 假設(shè)一秒有80脈沖,那么就是80cm/s
4.3 定時(shí)器和中斷實(shí)現(xiàn)測(cè)速開(kāi)發(fā)和調(diào)試代碼
測(cè)試數(shù)據(jù)通過(guò)串口發(fā)送到上位機(jī)
//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)計(jì)格子,脈沖次數(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)打開(kāi)了總中斷IT0 = 1;//外部中斷的下降沿觸發(fā)
}void main()
{Time0Init();//定時(shí)器0初始化UartInit();//串口相關(guān)初始化//外部中斷初始化Ex0Init();while(1){if(signal){//定時(shí)器1s到點(diǎn),把signal置一,主程序發(fā)送速度sprintf(speedMes,"speed:%d cm/s",speed);//串口數(shù)據(jù)的字符串拼裝,speed是格子,每個(gè)格子1cmSendString(speedMes);//速度發(fā)出去signal = 0;//清0speed,下次由定時(shí)器1s后的中斷處理中再置一}}
}void speedHandler() interrupt 0 //外部中斷處理函數(shù)
{speedCnt++;//碼盤(pán)轉(zhuǎn)動(dòng)了一個(gè)格子
}//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;//定時(shí)器1工作方式位8位自動(dòng)重裝TH1 = 0xFD;TL1 = 0xFD;//9600波特率的初值TR1 = 1;//啟動(dòng)定時(shí)器EA = 1;//開(kāi)啟總中斷ES = 1;//開(kāi)啟串口中斷
}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ù)中,對(duì)于接收中斷的響應(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. 配置定時(shí)器0工作模式位16位計(jì)時(shí)TMOD = 0x01;//2. 給初值,定一個(gè)0.5出來(lái)TL0=0x33;TH0=0xFE;//3. 開(kāi)始計(jì)時(shí)TR0 = 1;TF0 = 0;//4. 打開(kāi)定時(shí)器0中斷ET0 = 1;//5. 打開(kāi)總中斷EAEA = 1;
}void Time0Handler() interrupt 1
{cnt++; //統(tǒng)計(jì)爆表的次數(shù). cnt=1的時(shí)候,報(bào)表了1//重新給初值TL0=0x33;TH0=0xFE;if(cnt == 2000){//爆表2000次,經(jīng)過(guò)了1ssignal = 1;cnt = 0; //當(dāng)100次表示1s,重新讓cnt從0開(kāi)始,計(jì)算下一次的1s//計(jì)算小車(chē)的速度,也就是拿到speedCnt的值speed = speedCnt;speedCnt = 0;//1秒后拿到speedCnt個(gè)格子,就能算出這1s的速度,格子清零}}
4.4 小車(chē)速度顯示在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;//就在時(shí)鐘脈沖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ù)建立時(shí)間scl = 1;//scl拉高開(kāi)始發(fā)送_nop_();//數(shù)據(jù)發(fā)送時(shí)間scl = 0;//發(fā)送完畢拉低_nop_();//dataSend = dataSend << 1;}
}void Oled_Write_Cmd(char dataCmd)
{// 1. start()IIC_Start();// // 2. 寫(xiě)入從機(jī)地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 寫(xiě)入命令 (0)(1)000000寫(xiě)入數(shù)據(jù)IIC_Send_Byte(0x00);// 5. ACKIIC_ACK();//6. 寫(xiě)入指令/數(shù)據(jù)IIC_Send_Byte(dataCmd);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Write_Data(char dataData)
{// 1. start()IIC_Start();// // 2. 寫(xiě)入從機(jī)地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 寫(xiě)入命令 (0)(1)000000寫(xiě)入數(shù)據(jù)IIC_Send_Byte(0x40);// 5. ACKIIC_ACK();///6. 寫(xiě)入指令/數(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//每個(gè)page從0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//0到127列,依次寫(xiě)入0,每寫(xiě)入數(shù)據(jù),列地址自動(dòng)偏移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]); //寫(xiě)數(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]); //寫(xiě)數(shù)據(jù)oledTable1}
}/******************************************************************************/
// 函數(shù)名稱(chēng):Oled_Show_Char
// 輸入?yún)?shù):oledChar
// 輸出參數(shù):無(wú)
// 函數(shù)功能:OLED顯示單個(gè)字符
/******************************************************************************/
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)程控制小車(chē)
5.1 藍(lán)牙控制小車(chē)
- 使用藍(lán)牙模塊,串口透?jìng)?/li>
- 藍(lán)牙模塊,又叫做藍(lán)牙串口模塊
串口透?jìng)骷夹g(shù):
- 透?jìng)骷赐该鱾魉?#xff0c;是指在數(shù)據(jù)的傳輸過(guò)程中,通過(guò)無(wú)線的方式這組數(shù)據(jù)不發(fā)生任何形式的改變,仿 佛傳輸過(guò)程是透明的一樣,同時(shí)保證傳輸?shù)馁|(zhì)量,原封不動(dòng)地到了最終接收者手里。
- 以太網(wǎng),藍(lán)牙,Zigbee, GPRS 等模塊玩法一樣,對(duì)嵌入式程序員來(lái)說(shuō),不需要關(guān)心通訊模塊內(nèi)部數(shù)據(jù) 及協(xié)議棧工作原理,只要通過(guò)串口編程獲得數(shù)據(jù)即可
代碼實(shí)現(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;//定時(shí)器1工作方式位8位自動(dòng)重裝TH1 = 0xFD;TL1 = 0xFD;//9600波特率的初值TR1 = 1;//啟動(dòng)定時(shí)器EA = 1;//開(kāi)啟總中斷ES = 1;//開(kāi)啟串口中斷
}//M1qian M2 hou M3 zuo M4 you
void Uart_Handler() interrupt 4
{static int i = 0;//靜態(tài)變量,被初始化一次char tmp;if(RI)//中斷處理函數(shù)中,對(duì)于接收中斷的響應(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)牙控制并測(cè)速小車(chē)
原理:運(yùn)用上面講到的藍(lán)牙模塊和測(cè)速模塊
代碼實(shí)現(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)計(jì)格子,脈沖次數(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)打開(kāi)了總中斷IT0 = 1;//外部中斷的下降沿觸發(fā)
}void main()
{Time0Init();//定時(shí)器0初始化UartInit();//串口相關(guān)初始化//外部中斷初始化Ex0Init();Oled_Init();Oled_Clear();while(1){if(signal){//定時(shí)器1s到點(diǎn),把signal置一,主程序發(fā)送速度sprintf(speedMes,"speed:%d cm/s",speed);//串口數(shù)據(jù)的字符串拼裝,speed是格子,每個(gè)格子1cmSendString(speedMes);//速度發(fā)出去signal = 0;//清0speed,下次由定時(shí)器1s后的中斷處理中再置一}Oled_Show_Str(2,2,speedMes);}
}void speedHandler() interrupt 0 //外部中斷處理函數(shù)
{speedCnt++;//碼盤(pán)轉(zhuǎn)動(dòng)了一個(gè)格子
}//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;//定時(shí)器1工作方式位8位自動(dòng)重裝TH1 = 0xFD;TL1 = 0xFD;//9600波特率的初值TR1 = 1;//啟動(dòng)定時(shí)器EA = 1;//開(kāi)啟總中斷ES = 1;//開(kāi)啟串口中斷
}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ù)中,對(duì)于接收中斷的響應(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. 配置定時(shí)器0工作模式位16位計(jì)時(shí)TMOD = 0x01;//2. 給初值,定一個(gè)0.5出來(lái)TL0=0x33;TH0=0xFE;//3. 開(kāi)始計(jì)時(shí)TR0 = 1;TF0 = 0;//4. 打開(kāi)定時(shí)器0中斷ET0 = 1;//5. 打開(kāi)總中斷EAEA = 1;
}void Time0Handler() interrupt 1
{cnt++; //統(tǒng)計(jì)爆表的次數(shù). cnt=1的時(shí)候,報(bào)表了1//重新給初值TL0=0x33;TH0=0xFE;if(cnt == 2000){//爆表2000次,經(jīng)過(guò)了1ssignal = 1;cnt = 0; //當(dāng)100次表示1s,重新讓cnt從0開(kāi)始,計(jì)算下一次的1s//計(jì)算小車(chē)的速度,也就是拿到speedCnt的值speed = speedCnt;speedCnt = 0;//1秒后拿到speedCnt個(gè)格子,就能算出這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;//就在時(shí)鐘脈沖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ù)建立時(shí)間scl = 1;//scl拉高開(kāi)始發(fā)送_nop_();//數(shù)據(jù)發(fā)送時(shí)間scl = 0;//發(fā)送完畢拉低_nop_();//dataSend = dataSend << 1;}
}void Oled_Write_Cmd(char dataCmd)
{// 1. start()IIC_Start();// // 2. 寫(xiě)入從機(jī)地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 寫(xiě)入命令 (0)(1)000000寫(xiě)入數(shù)據(jù)IIC_Send_Byte(0x00);// 5. ACKIIC_ACK();//6. 寫(xiě)入指令/數(shù)據(jù)IIC_Send_Byte(dataCmd);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Write_Data(char dataData)
{// 1. start()IIC_Start();// // 2. 寫(xiě)入從機(jī)地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 寫(xiě)入命令 (0)(1)000000寫(xiě)入數(shù)據(jù)IIC_Send_Byte(0x40);// 5. ACKIIC_ACK();///6. 寫(xiě)入指令/數(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//每個(gè)page從0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//0到127列,依次寫(xiě)入0,每寫(xiě)入數(shù)據(jù),列地址自動(dòng)偏移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]); //寫(xiě)數(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]); //寫(xiě)數(shù)據(jù)oledTable1}
}/******************************************************************************/
// 函數(shù)名稱(chēng):Oled_Show_Char
// 輸入?yún)?shù):oledChar
// 輸出參數(shù):無(wú)
// 函數(shù)功能:OLED顯示單個(gè)字符
/******************************************************************************/
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控制測(cè)速小車(chē)
- Wifi模塊-ESP-01s
- 藍(lán)牙,ESP-01s,Zigbee, NB-Iot等通信模塊都是基于AT指令的設(shè)計(jì)
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ā)送的。
- 其對(duì)所傳輸?shù)臄?shù)據(jù)包大小有定義:即對(duì)于AT指令的發(fā)送,除AT兩個(gè)字符外,最多可以接收1056個(gè) 字符的長(zhǎng)度(包括最后的空字符)。
- 每個(gè)AT命令行中只能包含一條AT指令;對(duì)于由終端設(shè)備主動(dòng)向PC端報(bào)告的URC指示或者response 響應(yīng),也要求一行最多有一個(gè),不允許上報(bào)的一行中有多條指示或者響應(yīng)。AT指令以回車(chē)作為結(jié) 尾,響應(yīng)或上報(bào)以回車(chē)換行為結(jié)尾。
代碼實(shí)現(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)計(jì)格子,脈沖次數(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)打開(kāi)了總中斷IT0 = 1;//外部中斷的下降沿觸發(fā)
}void main()
{Time0Init();//定時(shí)器0初始化UartInit();//串口相關(guān)初始化Delay1000ms();//給espwifi模塊上電時(shí)間initWifi_AP(); //初始化wifi工作在ap模式waitConnect(); //等待客戶(hù)端的連接//外部中斷初始化Ex0Init();Oled_Init();Oled_Clear();while(1){if(signal){//定時(shí)器1s到點(diǎn),把signal置一,主程序發(fā)送速度SendString(FSSJ);Delay1000ms();sprintf(speedMes,"%dcms",speed);//串口數(shù)據(jù)的字符串拼裝,speed是格子,每個(gè)格子1cmSendString(speedMes);//速度發(fā)出去signal = 0;//清0speed,下次由定時(shí)器1s后的中斷處理中再置一}Oled_Show_Str(2,2,speedMes);}
}void speedHandler() interrupt 0 //外部中斷處理函數(shù)
{speedCnt++;//碼盤(pán)轉(zhuǎn)動(dòng)了一個(gè)格子
}//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;//定時(shí)器1工作方式位8位自動(dòng)重裝TH1 = 0xFD;TL1 = 0xFD;//9600波特率的初值TR1 = 1;//啟動(dòng)定時(shí)器EA = 1;//開(kāi)啟總中斷ES = 1;//開(kāi)啟串口中斷
}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ù)中,對(duì)于接收中斷的響應(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. 配置定時(shí)器0工作模式位16位計(jì)時(shí)TMOD = 0x01;//2. 給初值,定一個(gè)0.5出來(lái)TL0=0x33;TH0=0xFE;//3. 開(kāi)始計(jì)時(shí)TR0 = 1;TF0 = 0;//4. 打開(kāi)定時(shí)器0中斷ET0 = 1;//5. 打開(kāi)總中斷EAEA = 1;
}void Time0Handler() interrupt 1
{cnt++; //統(tǒng)計(jì)爆表的次數(shù). cnt=1的時(shí)候,報(bào)表了1//重新給初值TL0=0x33;TH0=0xFE;if(cnt == 2000){//爆表2000次,經(jīng)過(guò)了1ssignal = 1;cnt = 0; //當(dāng)100次表示1s,重新讓cnt從0開(kāi)始,計(jì)算下一次的1s//計(jì)算小車(chē)的速度,也就是拿到speedCnt的值speed = speedCnt;speedCnt = 0;//1秒后拿到speedCnt個(gè)格子,就能算出這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;//就在時(shí)鐘脈沖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ù)建立時(shí)間scl = 1;//scl拉高開(kāi)始發(fā)送_nop_();//數(shù)據(jù)發(fā)送時(shí)間scl = 0;//發(fā)送完畢拉低_nop_();//dataSend = dataSend << 1;}
}void Oled_Write_Cmd(char dataCmd)
{// 1. start()IIC_Start();// // 2. 寫(xiě)入從機(jī)地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 寫(xiě)入命令 (0)(1)000000寫(xiě)入數(shù)據(jù)IIC_Send_Byte(0x00);// 5. ACKIIC_ACK();//6. 寫(xiě)入指令/數(shù)據(jù)IIC_Send_Byte(dataCmd);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Write_Data(char dataData)
{// 1. start()IIC_Start();// // 2. 寫(xiě)入從機(jī)地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 寫(xiě)入命令 (0)(1)000000寫(xiě)入數(shù)據(jù)IIC_Send_Byte(0x40);// 5. ACKIIC_ACK();///6. 寫(xiě)入指令/數(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//每個(gè)page從0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//0到127列,依次寫(xiě)入0,每寫(xiě)入數(shù)據(jù),列地址自動(dòng)偏移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]); //寫(xiě)數(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]); //寫(xiě)數(shù)據(jù)oledTable1}
}/******************************************************************************/
// 函數(shù)名稱(chēng):Oled_Show_Char
// 輸入?yún)?shù):oledChar
// 輸出參數(shù):無(wú)
// 函數(shù)功能:OLED顯示單個(gè)字符
/******************************************************************************/
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控制小車(chē)
原理:運(yùn)用EC03-DNC4G通信模塊
模塊介紹:
- 基于串口AT指令的開(kāi)發(fā)方式
- 有兩種工作模式,默認(rèn)是透?jìng)髂J?#xff0c;通過(guò)其他方式進(jìn)入AT指令模式
- 注意插卡不要出錯(cuò),下圖紅色位置為SIM卡狀態(tài)燈,亮才是正常
代碼不做修改,直接基于藍(lán)牙小車(chē)整合,?4g模塊只要做好外網(wǎng)透?jìng)骶涂梢粤?/p>
6.語(yǔ)音控制小車(chē)
6.1語(yǔ)音模塊配置:
使用SU-03T / LD3320
具體介紹看我之前寫(xiě)過(guò)的博客:https://blog.csdn.net/m0_74712453/article/details/13171085
6.2 語(yǔ)音控制小車(chē)開(kāi)發(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();//測(cè)左邊距離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();//舵機(jī)的初始位置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è)置定時(shí)器模式TMOD |= 0x10;TH1 = 0;TL1 = 0;//設(shè)置定時(shí)器0工作模式1,初始值設(shè)定0開(kāi)始數(shù)數(shù),不著急啟動(dòng)定時(shí)器
}void startHC()
{Trig = 0;Trig = 1;Delay10us();Trig = 0;
}double get_distance()
{double time;//定時(shí)器數(shù)據(jù)清零,以便下一次測(cè)距TH1 = 0;TL1 = 0;//1. Trig ,給Trig端口至少10us的高電平startHC();//2. echo由低電平跳轉(zhuǎn)到高電平,表示開(kāi)始發(fā)送波while(Echo == 0);//波發(fā)出去的那一下,開(kāi)始啟動(dòng)定時(shí)器TR1 = 1;//3. 由高電平跳轉(zhuǎn)回低電平,表示波回來(lái)了while(Echo == 1);//波回來(lái)的那一下,我們開(kāi)始停止定時(shí)器TR1 = 0;//4. 計(jì)算出中間經(jīng)過(guò)多少時(shí)間time = (TH1 * 256 + TL1)*1.085;//us為單位//5. 距離 = 速度 (340m/s)* 時(shí)間/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. 配置定時(shí)器0工作模式位16位計(jì)時(shí)TMOD &= 0xF0; //設(shè)置定時(shí)器模式TMOD |= 0x01;//2. 給初值,定一個(gè)0.5出來(lái)TL0=0x33;TH0=0xFE;//3. 開(kāi)始計(jì)時(shí)TR0 = 1;TF0 = 0;//4. 打開(kāi)定時(shí)器0中斷ET0 = 1;//5. 打開(kāi)總中斷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)計(jì)爆表的次數(shù). cnt=1的時(shí)候,報(bào)表了1//重新給初值TL0=0x33;TH0=0xFE;//控制PWM波if(cnt < jd){sg90_con = 1;}else{sg90_con = 0;}if(cnt == 40){//爆表40次,經(jīng)過(guò)了20mscnt = 0; //當(dāng)100次表示1s,重新讓cnt從0開(kāi)始,計(jì)算下一次的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;//就在時(shí)鐘脈沖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ù)建立時(shí)間scl = 1;//scl拉高開(kāi)始發(fā)送_nop_();//數(shù)據(jù)發(fā)送時(shí)間scl = 0;//發(fā)送完畢拉低_nop_();//dataSend = dataSend << 1;}
}void Oled_Write_Cmd(char dataCmd)
{// 1. start()IIC_Start();// // 2. 寫(xiě)入從機(jī)地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 寫(xiě)入命令 (0)(1)000000寫(xiě)入數(shù)據(jù)IIC_Send_Byte(0x00);// 5. ACKIIC_ACK();//6. 寫(xiě)入指令/數(shù)據(jù)IIC_Send_Byte(dataCmd);//7. ACKIIC_ACK();//8. STOPIIC_Stop();
}void Oled_Write_Data(char dataData)
{// 1. start()IIC_Start();// // 2. 寫(xiě)入從機(jī)地址 b0111 1000 0x78IIC_Send_Byte(0x78);// 3. ACKIIC_ACK();// 4. cotrol byte: (0)(0)000000 寫(xiě)入命令 (0)(1)000000寫(xiě)入數(shù)據(jù)IIC_Send_Byte(0x40);// 5. ACKIIC_ACK();///6. 寫(xiě)入指令/數(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//每個(gè)page從0列Oled_Write_Cmd(0x00);Oled_Write_Cmd(0x10);//0到127列,依次寫(xiě)入0,每寫(xiě)入數(shù)據(jù),列地址自動(dòng)偏移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]); //寫(xiě)數(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]); //寫(xiě)數(shù)據(jù)oledTable1}
}/******************************************************************************/
// 函數(shù)名稱(chēng):Oled_Show_Char
// 輸入?yún)?shù):oledChar
// 輸出參數(shù):無(wú)
// 函數(shù)功能:OLED顯示單個(gè)字符
/******************************************************************************/
void Oled_Show_Str(char row,char col,char *str){while(*str!=0){Oled_Show_Char(row,col,*str);str++;col += 8; }
}
???????