赞
踩
有需要帮忙代做51和32小车或者其他单片机项目,课程设计,报告,PCB原理图的小伙伴,可以在文章最下方加我V交流咨询!!!
目录
L9110s概述
接通VCC,GND 模块电源指示灯亮, 以下资料来源官方,具体根据实际调试
IA1输入高电平,IA1输入低电平,【OA1 OB1】电机正转;
IA1输入低电平,IA1输入高电平,【OA1 OB1】电机反转;
IA2输入高电平,IA2输入低电平,【OA2 OB2】电机正转;
IA2输入低电平,IA2输入高电平,【OA2 OB2】电机反转;
核心代码:
- #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();
- }
- }
-
-
原理: 全速前进是LeftCon1A = 0; LeftCon1B = 1;完全停止是LeftCon1A = 0;LeftCon1B = 0;那么单位时 间内,比如20ms, 有15ms是全速前进,5ms是完全停止, 速度就会比5ms全速前进,15ms完全停止获得的功率多,相应的速度更快!
开发:借用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份的500us
- Delay1000ms();
- 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. 打开总中断EA
- EA = 1;
- }
-
- void Time0Handler() interrupt 1
- {
- cnt++; //统计爆表的次数. cnt=1的时候,报表了1
- //重新给初值
- TL0=0x33;
- TH0=0xFE;
-
- //控制PWM波
- if(cnt < speed){
- //前进
- goForward();
- }else{
- //停止
- stop();
- }
-
- if(cnt == 40){//爆表40次,经过了20ms
- cnt = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
- }
-
- }
原理: 左轮定时器0调速,右轮定时器1调速,那么左转就是右轮速度大于左轮!
核心代码:
- #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. 打开总中断EA
- EA = 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. 打开总中断EA
- EA = 1;
- }
-
- void Time1Handler() interrupt 3
- {
- cntRight++; //统计爆表的次数. cnt=1的时候,报表了1
- //重新给初值
- TL1=0x33;
- TH1=0xFE;
-
- //控制PWM波
- if(cntRight < speedRight){
- //右前进
- goForwardRight();
- }else{
- //停止
- stopRight();
- }
-
- if(cntRight == 40){//爆表40次,经过了20ms
- cntRight = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
- }
-
- }
-
- void Time0Handler() interrupt 1
- {
- cntLeft++; //统计爆表的次数. cnt=1的时候,报表了1
- //重新给初值
- TL0=0x33;
- TH0=0xFE;
-
- //控制PWM波
- if(cntLeft < speedLeft){
- //左前进
- goForwardLeft();
- }else{
- //停止
- stopLeft();
- }
-
- if(cntLeft == 40){//爆表40次,经过了20ms
- cntLeft = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
- }
-
- }
接线方式
由于黑色具有较强的吸收能力,当循迹模块发射的红外线照射到黑线时,红外线将会被黑线吸收,导致 循迹模块上光敏三极管处于关闭状态,此时模块上一个LED熄灭。在没有检测到黑线时,模块上两个LED常亮
总结就是一句话,有感应到黑线,D0输出高电平 ,灭灯
- //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份的500us
- speedRight = 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. 打开总中断EA
- EA = 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. 打开总中断EA
- EA = 1;
- }
-
- void Time1Handler() interrupt 3
- {
- cntRight++; //统计爆表的次数. cnt=1的时候,报表了1
- //重新给初值
- TL1=0x33;
- TH1=0xFE;
-
- //控制PWM波
- if(cntRight < speedRight){
- //右前进
- goForwardRight();
- }else{
- //停止
- stopRight();
- }
-
- if(cntRight == 40){//爆表40次,经过了20ms
- cntRight = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
- }
-
- }
-
- void Time0Handler() interrupt 1
- {
- cntLeft++; //统计爆表的次数. cnt=1的时候,报表了1
- //重新给初值
- TL0=0x33;
- TH0=0xFE;
-
- //控制PWM波
- if(cntLeft < speedLeft){
- //左前进
- goForwardLeft();
- }else{
- //停止
- stopLeft();
- }
-
- if(cntLeft == 40){//爆表40次,经过了20ms
- cntLeft = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
- }
-
- }
-
原理和循迹是一样的,循迹红外观朝下,跟随朝前
- //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);
- }
-
-
-
使用超声波模块,型号:HC-SR04
时序图:
- //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 2
-
- void 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){
- //前进
- 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; //设置定时器模式
- TMOD |= 0x10;
- TH1 = 0;
- TL1 = 0;
- //设置定时器0工作模式1,初始值设定0开始数数,不着急启动定时器
- }
-
- void startHC()
- {
- Trig = 0;
- Trig = 1;
- Delay10us();
- Trig = 0;
- }
-
- double get_distance()
- {
- double time;
- //定时器数据清零,以便下一次测距
- TH1 = 0;
- TL1 = 0;
- //1. Trig ,给Trig端口至少10us的高电平
- startHC();
- //2. echo由低电平跳转到高电平,表示开始发送波
- while(Echo == 0);
- //波发出去的那一下,开始启动定时器
- TR1 = 1;
- //3. 由高电平跳转回低电平,表示波回来了
- while(Echo == 1);
- //波回来的那一下,我们开始停止定时器
- TR1 = 0;
- //4. 计算出中间经过多少时间
- time = (TH1 * 256 + TL1)*1.085;//us为单位
- //5. 距离 = 速度 (340m/s)* 时间/2
- return (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; //设置定时器模式
- TMOD |= 0x01;
- //2. 给初值,定一个0.5出来
- TL0=0x33;
- TH0=0xFE;
- //3. 开始计时
- TR0 = 1;
- TF0 = 0;
- //4. 打开定时器0中断
- ET0 = 1;
- //5. 打开总中断EA
- EA = 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++; //统计爆表的次数. cnt=1的时候,报表了1
- //重新给初值
- TL0=0x33;
- TH0=0xFE;
-
- //控制PWM波
- if(cnt < jd){
- sg90_con = 1;
- }else{
- sg90_con = 0;
- }
-
- if(cnt == 40){//爆表40次,经过了20ms
- cnt = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
- sg90_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;
- }
-
-
-
-
-
-
测试数据通过串口发送到上位机
- //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; //统计格子,脉冲次数
- extern unsigned int speed;//速度
- extern char signal; //主程序发速度数据的通知
- char speedMes[24]; //主程序发送速度数据的字符串缓冲区
-
- void Ex0Init()
- {
- EX0 = 1;//允许中断
- //EA = 1;在串口初始化函数中已经打开了总中断
- IT0 = 1;//外部中断的下降沿触发
- }
-
- void main()
- {
- Time0Init();//定时器0初始化
- UartInit();//串口相关初始化
- //外部中断初始化
- Ex0Init();
-
- while(1){
- if(signal){//定时器1s到点,把signal置一,主程序发送速度
- sprintf(speedMes,"speed:%d cm/s",speed);//串口数据的字符串拼装,speed是格子,每个格子1cm
- SendString(speedMes);//速度发出去
- signal = 0;//清0speed,下次由定时器1s后的中断处理中再置一
- }
- }
- }
-
- void speedHandler() interrupt 0 //外部中断处理函数
- {
- speedCnt++;//码盘转动了一个格子
- }
-
- //uart.c
- #include "reg52.h"
- #include "motor.h"
- #include "string.h"
- sbit D5 = P3^7;
- #define SIZE 12
-
- sfr 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;//静态变量,被初始化一次
- char tmp;
-
- if(RI)//中断处理函数中,对于接收中断的响应
- {
- RI = 0;//清除接收中断标志位
- 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. 打开总中断EA
- EA = 1;
- }
-
- void Time0Handler() interrupt 1
- {
- cnt++; //统计爆表的次数. cnt=1的时候,报表了1
- //重新给初值
- TL0=0x33;
- TH0=0xFE;
-
- if(cnt == 2000){//爆表2000次,经过了1s
- signal = 1;
- cnt = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
- //计算小车的速度,也就是拿到speedCnt的值
- speed = speedCnt;
- speedCnt = 0;//1秒后拿到speedCnt个格子,就能算出这1s的速度,格子清零
- }
-
- }
使用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期间释放数据线
- _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做好数据准备
- sda = dataSend & 0x80;//1000 0000获得dataSend的最高位,给sda
- _nop_();//发送数据建立时间
- scl = 1;//scl拉高开始发送
- _nop_();//数据发送时间
- scl = 0;//发送完毕拉低
- _nop_();//
- dataSend = dataSend << 1;
- }
- }
-
- void Oled_Write_Cmd(char dataCmd)
- {
- // 1. start()
- IIC_Start();
- //
- // 2. 写入从机地址 b0111 1000 0x78
- IIC_Send_Byte(0x78);
- // 3. ACK
- IIC_ACK();
- // 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
- IIC_Send_Byte(0x00);
- // 5. ACK
- IIC_ACK();
- //6. 写入指令/数据
- IIC_Send_Byte(dataCmd);
- //7. ACK
- IIC_ACK();
- //8. STOP
- IIC_Stop();
- }
-
- void Oled_Write_Data(char dataData)
- {
- // 1. start()
- IIC_Start();
- //
- // 2. 写入从机地址 b0111 1000 0x78
- IIC_Send_Byte(0x78);
- // 3. ACK
- IIC_ACK();
- // 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
- IIC_Send_Byte(0x40);
- // 5. ACK
- IIC_ACK();
- ///6. 写入指令/数据
- IIC_Send_Byte(dataData);
- //7. ACK
- IIC_ACK();
- //8. STOP
- IIC_Stop();
- }
-
-
- void Oled_Init(void){
- Oled_Write_Cmd(0xAE);//--display off
- Oled_Write_Cmd(0x00);//---set low column address
- Oled_Write_Cmd(0x10);//---set high column address
- Oled_Write_Cmd(0x40);//--set start line address
- Oled_Write_Cmd(0xB0);//--set page address
- Oled_Write_Cmd(0x81); // contract control
- Oled_Write_Cmd(0xFF);//--128
- Oled_Write_Cmd(0xA1);//set segment remap
- Oled_Write_Cmd(0xA6);//--normal / reverse
- Oled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
- Oled_Write_Cmd(0x3F);//--1/32 duty
- Oled_Write_Cmd(0xC8);//Com scan direction
- Oled_Write_Cmd(0xD3);//-set display offset
- Oled_Write_Cmd(0x00);//
-
- Oled_Write_Cmd(0xD5);//set osc division
- Oled_Write_Cmd(0x80);//
-
- Oled_Write_Cmd(0xD8);//set area color mode off
- Oled_Write_Cmd(0x05);//
-
- Oled_Write_Cmd(0xD9);//Set Pre-Charge Period
- Oled_Write_Cmd(0xF1);//
-
- Oled_Write_Cmd(0xDA);//set com pin configuartion
- Oled_Write_Cmd(0x12);//
-
- Oled_Write_Cmd(0xDB);//set Vcomh
- Oled_Write_Cmd(0x30);//
-
- Oled_Write_Cmd(0x8D);//set charge pump enable
- Oled_Write_Cmd(0x14);//
-
- Oled_Write_Cmd(0xAF);//--turn on oled panel
- }
-
- void Oled_Clear()
- {
- unsigned char i,j; //-128 --- 127
-
- for(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,每写入数据,列地址自动偏移
- for(j = 0;j<128;j++){
- Oled_Write_Data(0);
- }
- }
- }
-
- void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2
- unsigned int i;
- Oled_Write_Cmd(0xb0+(row*2-2)); //page 0
- Oled_Write_Cmd(0x00+(col&0x0f)); //low
- Oled_Write_Cmd(0x10+(col>>4)); //high
- for(i=((oledChar-32)*16);i<((oledChar-32)*16+8);i++){
- Oled_Write_Data(F8X16[i]); //写数据oledTable1
- }
-
- Oled_Write_Cmd(0xb0+(row*2-1)); //page 1
- Oled_Write_Cmd(0x00+(col&0x0f)); //low
- Oled_Write_Cmd(0x10+(col>>4)); //high
- for(i=((oledChar-32)*16+8);i<((oledChar-32)*16+8+8);i++){
- Oled_Write_Data(F8X16[i]); //写数据oledTable1
- }
- }
-
-
- /******************************************************************************/
- // 函数名称:Oled_Show_Char
- // 输入参数:oledChar
- // 输出参数:无
- // 函数功能:OLED显示单个字符
- /******************************************************************************/
- void Oled_Show_Str(char row,char col,char *str){
- while(*str!=0){
- Oled_Show_Char(row,col,*str);
- str++;
- col += 8;
- }
- }
串口透传技术:
代码实现:
- //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 12
-
- sfr 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;//静态变量,被初始化一次
- char tmp;
-
- if(RI)//中断处理函数中,对于接收中断的响应
- {
- RI = 0;//清除接收中断标志位
- 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);
- }
-
-
-
原理:运用上面讲到的蓝牙模块和测速模块
代码实现:
- //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; //统计格子,脉冲次数
- extern unsigned int speed;//速度
- extern char signal; //主程序发速度数据的通知
- char speedMes[24]; //主程序发送速度数据的字符串缓冲区
-
- void Ex0Init()
- {
- EX0 = 1;//允许中断
- //EA = 1;在串口初始化函数中已经打开了总中断
- IT0 = 1;//外部中断的下降沿触发
- }
-
- void main()
- {
- Time0Init();//定时器0初始化
- UartInit();//串口相关初始化
- //外部中断初始化
- Ex0Init();
- Oled_Init();
- Oled_Clear();
- while(1){
- if(signal){//定时器1s到点,把signal置一,主程序发送速度
- sprintf(speedMes,"speed:%d cm/s",speed);//串口数据的字符串拼装,speed是格子,每个格子1cm
- SendString(speedMes);//速度发出去
-
- signal = 0;//清0speed,下次由定时器1s后的中断处理中再置一
- }
- Oled_Show_Str(2,2,speedMes);
- }
- }
-
- void speedHandler() interrupt 0 //外部中断处理函数
- {
- speedCnt++;//码盘转动了一个格子
- }
-
- //uart.c
- #include "reg52.h"
- #include "motor.h"
- #include "string.h"
- sbit D5 = P3^7;
- #define SIZE 12
-
- sfr 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;//静态变量,被初始化一次
- char tmp;
-
- if(RI)//中断处理函数中,对于接收中断的响应
- {
- RI = 0;//清除接收中断标志位
- 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. 打开总中断EA
- EA = 1;
- }
-
- void Time0Handler() interrupt 1
- {
- cnt++; //统计爆表的次数. cnt=1的时候,报表了1
- //重新给初值
- TL0=0x33;
- TH0=0xFE;
-
- if(cnt == 2000){//爆表2000次,经过了1s
- signal = 1;
- cnt = 0; //当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期间释放数据线
- _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做好数据准备
- sda = dataSend & 0x80;//1000 0000获得dataSend的最高位,给sda
- _nop_();//发送数据建立时间
- scl = 1;//scl拉高开始发送
- _nop_();//数据发送时间
- scl = 0;//发送完毕拉低
- _nop_();//
- dataSend = dataSend << 1;
- }
- }
-
- void Oled_Write_Cmd(char dataCmd)
- {
- // 1. start()
- IIC_Start();
- //
- // 2. 写入从机地址 b0111 1000 0x78
- IIC_Send_Byte(0x78);
- // 3. ACK
- IIC_ACK();
- // 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
- IIC_Send_Byte(0x00);
- // 5. ACK
- IIC_ACK();
- //6. 写入指令/数据
- IIC_Send_Byte(dataCmd);
- //7. ACK
- IIC_ACK();
- //8. STOP
- IIC_Stop();
- }
-
- void Oled_Write_Data(char dataData)
- {
- // 1. start()
- IIC_Start();
- //
- // 2. 写入从机地址 b0111 1000 0x78
- IIC_Send_Byte(0x78);
- // 3. ACK
- IIC_ACK();
- // 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
- IIC_Send_Byte(0x40);
- // 5. ACK
- IIC_ACK();
- ///6. 写入指令/数据
- IIC_Send_Byte(dataData);
- //7. ACK
- IIC_ACK();
- //8. STOP
- IIC_Stop();
- }
-
-
- void Oled_Init(void){
- Oled_Write_Cmd(0xAE);//--display off
- Oled_Write_Cmd(0x00);//---set low column address
- Oled_Write_Cmd(0x10);//---set high column address
- Oled_Write_Cmd(0x40);//--set start line address
- Oled_Write_Cmd(0xB0);//--set page address
- Oled_Write_Cmd(0x81); // contract control
- Oled_Write_Cmd(0xFF);//--128
- Oled_Write_Cmd(0xA1);//set segment remap
- Oled_Write_Cmd(0xA6);//--normal / reverse
- Oled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
- Oled_Write_Cmd(0x3F);//--1/32 duty
- Oled_Write_Cmd(0xC8);//Com scan direction
- Oled_Write_Cmd(0xD3);//-set display offset
- Oled_Write_Cmd(0x00);//
-
- Oled_Write_Cmd(0xD5);//set osc division
- Oled_Write_Cmd(0x80);//
-
- Oled_Write_Cmd(0xD8);//set area color mode off
- Oled_Write_Cmd(0x05);//
-
- Oled_Write_Cmd(0xD9);//Set Pre-Charge Period
- Oled_Write_Cmd(0xF1);//
-
- Oled_Write_Cmd(0xDA);//set com pin configuartion
- Oled_Write_Cmd(0x12);//
-
- Oled_Write_Cmd(0xDB);//set Vcomh
- Oled_Write_Cmd(0x30);//
-
- Oled_Write_Cmd(0x8D);//set charge pump enable
- Oled_Write_Cmd(0x14);//
-
- Oled_Write_Cmd(0xAF);//--turn on oled panel
- }
-
- void Oled_Clear()
- {
- unsigned char i,j; //-128 --- 127
-
- for(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,每写入数据,列地址自动偏移
- for(j = 0;j<128;j++){
- Oled_Write_Data(0);
- }
- }
- }
-
- void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2
- unsigned int i;
- Oled_Write_Cmd(0xb0+(row*2-2)); //page 0
- Oled_Write_Cmd(0x00+(col&0x0f)); //low
- Oled_Write_Cmd(0x10+(col>>4)); //high
- for(i=((oledChar-32)*16);i<((oledChar-32)*16+8);i++){
- Oled_Write_Data(F8X16[i]); //写数据oledTable1
- }
-
- Oled_Write_Cmd(0xb0+(row*2-1)); //page 1
- Oled_Write_Cmd(0x00+(col&0x0f)); //low
- Oled_Write_Cmd(0x10+(col>>4)); //high
- for(i=((oledChar-32)*16+8);i<((oledChar-32)*16+8+8);i++){
- Oled_Write_Data(F8X16[i]); //写数据oledTable1
- }
- }
-
-
- /******************************************************************************/
- // 函数名称:Oled_Show_Char
- // 输入参数:oledChar
- // 输出参数:无
- // 函数功能:OLED显示单个字符
- /******************************************************************************/
- void Oled_Show_Str(char row,char col,char *str){
- while(*str!=0){
- Oled_Show_Char(row,col,*str);
- str++;
- col += 8;
- }
- }
-
AT指令介绍:
代码实现:
- //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; //统计格子,脉冲次数
- extern unsigned int speed;//速度
- extern char signal; //主程序发速度数据的通知
- char speedMes[24]; //主程序发送速度数据的字符串缓冲区
- //发送数据
- char FSSJ[] = "AT+CIPSEND=0,5\r\n";
-
- void Ex0Init()
- {
- EX0 = 1;//允许中断
- //EA = 1;在串口初始化函数中已经打开了总中断
- IT0 = 1;//外部中断的下降沿触发
- }
-
- void main()
- {
- Time0Init();//定时器0初始化
- UartInit();//串口相关初始化
- Delay1000ms();//给espwifi模块上电时间
-
- initWifi_AP(); //初始化wifi工作在ap模式
- waitConnect(); //等待客户端的连接
-
- //外部中断初始化
- Ex0Init();
- Oled_Init();
- Oled_Clear();
- while(1){
- if(signal){//定时器1s到点,把signal置一,主程序发送速度
- SendString(FSSJ);
- Delay1000ms();
- sprintf(speedMes,"%dcms",speed);//串口数据的字符串拼装,speed是格子,每个格子1cm
- SendString(speedMes);//速度发出去
-
- signal = 0;//清0speed,下次由定时器1s后的中断处理中再置一
- }
- Oled_Show_Str(2,2,speedMes);
- }
- }
-
- void speedHandler() interrupt 0 //外部中断处理函数
- {
- speedCnt++;//码盘转动了一个格子
- }
-
- //uart.c
- #include "reg52.h"
- #include "motor.h"
- #include "string.h"
- sbit D5 = P3^7;
- #define SIZE 12
-
- sfr AUXR = 0x8E;
- char buffer[SIZE];
-
- extern char AT_OK_Flag; //OK返回值的标志位
- 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;//静态变量,被初始化一次
- char tmp;
-
- if(RI)//中断处理函数中,对于接收中断的响应
- {
- RI = 0;//清除接收中断标志位
- tmp = SBUF;
- if(tmp == 'M' || tmp == 'O' || tmp == '0'){
- i = 0;
- }
- buffer[i++] = tmp;
-
- //连接服务器等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. 打开总中断EA
- EA = 1;
- }
-
- void Time0Handler() interrupt 1
- {
- cnt++; //统计爆表的次数. cnt=1的时候,报表了1
- //重新给初值
- TL0=0x33;
- TH0=0xFE;
-
- if(cnt == 2000){//爆表2000次,经过了1s
- signal = 1;
- cnt = 0; //当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期间释放数据线
- _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做好数据准备
- sda = dataSend & 0x80;//1000 0000获得dataSend的最高位,给sda
- _nop_();//发送数据建立时间
- scl = 1;//scl拉高开始发送
- _nop_();//数据发送时间
- scl = 0;//发送完毕拉低
- _nop_();//
- dataSend = dataSend << 1;
- }
- }
-
- void Oled_Write_Cmd(char dataCmd)
- {
- // 1. start()
- IIC_Start();
- //
- // 2. 写入从机地址 b0111 1000 0x78
- IIC_Send_Byte(0x78);
- // 3. ACK
- IIC_ACK();
- // 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
- IIC_Send_Byte(0x00);
- // 5. ACK
- IIC_ACK();
- //6. 写入指令/数据
- IIC_Send_Byte(dataCmd);
- //7. ACK
- IIC_ACK();
- //8. STOP
- IIC_Stop();
- }
-
- void Oled_Write_Data(char dataData)
- {
- // 1. start()
- IIC_Start();
- //
- // 2. 写入从机地址 b0111 1000 0x78
- IIC_Send_Byte(0x78);
- // 3. ACK
- IIC_ACK();
- // 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
- IIC_Send_Byte(0x40);
- // 5. ACK
- IIC_ACK();
- ///6. 写入指令/数据
- IIC_Send_Byte(dataData);
- //7. ACK
- IIC_ACK();
- //8. STOP
- IIC_Stop();
- }
-
-
- void Oled_Init(void){
- Oled_Write_Cmd(0xAE);//--display off
- Oled_Write_Cmd(0x00);//---set low column address
- Oled_Write_Cmd(0x10);//---set high column address
- Oled_Write_Cmd(0x40);//--set start line address
- Oled_Write_Cmd(0xB0);//--set page address
- Oled_Write_Cmd(0x81); // contract control
- Oled_Write_Cmd(0xFF);//--128
- Oled_Write_Cmd(0xA1);//set segment remap
- Oled_Write_Cmd(0xA6);//--normal / reverse
- Oled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
- Oled_Write_Cmd(0x3F);//--1/32 duty
- Oled_Write_Cmd(0xC8);//Com scan direction
- Oled_Write_Cmd(0xD3);//-set display offset
- Oled_Write_Cmd(0x00);//
-
- Oled_Write_Cmd(0xD5);//set osc division
- Oled_Write_Cmd(0x80);//
-
- Oled_Write_Cmd(0xD8);//set area color mode off
- Oled_Write_Cmd(0x05);//
-
- Oled_Write_Cmd(0xD9);//Set Pre-Charge Period
- Oled_Write_Cmd(0xF1);//
-
- Oled_Write_Cmd(0xDA);//set com pin configuartion
- Oled_Write_Cmd(0x12);//
-
- Oled_Write_Cmd(0xDB);//set Vcomh
- Oled_Write_Cmd(0x30);//
-
- Oled_Write_Cmd(0x8D);//set charge pump enable
- Oled_Write_Cmd(0x14);//
-
- Oled_Write_Cmd(0xAF);//--turn on oled panel
- }
-
- void Oled_Clear()
- {
- unsigned char i,j; //-128 --- 127
-
- for(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,每写入数据,列地址自动偏移
- for(j = 0;j<128;j++){
- Oled_Write_Data(0);
- }
- }
- }
-
- void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2
- unsigned int i;
- Oled_Write_Cmd(0xb0+(row*2-2)); //page 0
- Oled_Write_Cmd(0x00+(col&0x0f)); //low
- Oled_Write_Cmd(0x10+(col>>4)); //high
- for(i=((oledChar-32)*16);i<((oledChar-32)*16+8);i++){
- Oled_Write_Data(F8X16[i]); //写数据oledTable1
- }
-
- Oled_Write_Cmd(0xb0+(row*2-1)); //page 1
- Oled_Write_Cmd(0x00+(col&0x0f)); //low
- Oled_Write_Cmd(0x10+(col>>4)); //high
- for(i=((oledChar-32)*16+8);i<((oledChar-32)*16+8+8);i++){
- Oled_Write_Data(F8X16[i]); //写数据oledTable1
- }
- }
-
-
- /******************************************************************************/
- // 函数名称:Oled_Show_Char
- // 输入参数:oledChar
- // 输出参数:无
- // 函数功能: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返回值的标志位
- 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);
- }
-
原理:运用EC03-DNC4G通信模块
模块介绍:
代码不做修改,直接基于蓝牙小车整合, 4g模块只要做好外网透传就可以了
使用SU-03T / LD3320
具体介绍看我之前写过的博客:SU-03T语音模块的使用_罗小白的干爹的博客-CSDN博客
代码示例:
- //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 3
-
-
- sbit 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){
- //前进
- 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; //设置定时器模式
- TMOD |= 0x10;
- TH1 = 0;
- TL1 = 0;
- //设置定时器0工作模式1,初始值设定0开始数数,不着急启动定时器
- }
-
- void startHC()
- {
- Trig = 0;
- Trig = 1;
- Delay10us();
- Trig = 0;
- }
-
- double get_distance()
- {
- double time;
- //定时器数据清零,以便下一次测距
- TH1 = 0;
- TL1 = 0;
- //1. Trig ,给Trig端口至少10us的高电平
- startHC();
- //2. echo由低电平跳转到高电平,表示开始发送波
- while(Echo == 0);
- //波发出去的那一下,开始启动定时器
- TR1 = 1;
- //3. 由高电平跳转回低电平,表示波回来了
- while(Echo == 1);
- //波回来的那一下,我们开始停止定时器
- TR1 = 0;
- //4. 计算出中间经过多少时间
- time = (TH1 * 256 + TL1)*1.085;//us为单位
- //5. 距离 = 速度 (340m/s)* 时间/2
- return (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; //设置定时器模式
- TMOD |= 0x01;
- //2. 给初值,定一个0.5出来
- TL0=0x33;
- TH0=0xFE;
- //3. 开始计时
- TR0 = 1;
- TF0 = 0;
- //4. 打开定时器0中断
- ET0 = 1;
- //5. 打开总中断EA
- EA = 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++; //统计爆表的次数. cnt=1的时候,报表了1
- //重新给初值
- TL0=0x33;
- TH0=0xFE;
-
- //控制PWM波
- if(cnt < jd){
- sg90_con = 1;
- }else{
- sg90_con = 0;
- }
-
- if(cnt == 40){//爆表40次,经过了20ms
- cnt = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
- sg90_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期间释放数据线
- _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做好数据准备
- sda = dataSend & 0x80;//1000 0000获得dataSend的最高位,给sda
- _nop_();//发送数据建立时间
- scl = 1;//scl拉高开始发送
- _nop_();//数据发送时间
- scl = 0;//发送完毕拉低
- _nop_();//
- dataSend = dataSend << 1;
- }
- }
-
- void Oled_Write_Cmd(char dataCmd)
- {
- // 1. start()
- IIC_Start();
- //
- // 2. 写入从机地址 b0111 1000 0x78
- IIC_Send_Byte(0x78);
- // 3. ACK
- IIC_ACK();
- // 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
- IIC_Send_Byte(0x00);
- // 5. ACK
- IIC_ACK();
- //6. 写入指令/数据
- IIC_Send_Byte(dataCmd);
- //7. ACK
- IIC_ACK();
- //8. STOP
- IIC_Stop();
- }
-
- void Oled_Write_Data(char dataData)
- {
- // 1. start()
- IIC_Start();
- //
- // 2. 写入从机地址 b0111 1000 0x78
- IIC_Send_Byte(0x78);
- // 3. ACK
- IIC_ACK();
- // 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
- IIC_Send_Byte(0x40);
- // 5. ACK
- IIC_ACK();
- ///6. 写入指令/数据
- IIC_Send_Byte(dataData);
- //7. ACK
- IIC_ACK();
- //8. STOP
- IIC_Stop();
- }
-
-
- void Oled_Init(void){
- Oled_Write_Cmd(0xAE);//--display off
- Oled_Write_Cmd(0x00);//---set low column address
- Oled_Write_Cmd(0x10);//---set high column address
- Oled_Write_Cmd(0x40);//--set start line address
- Oled_Write_Cmd(0xB0);//--set page address
- Oled_Write_Cmd(0x81); // contract control
- Oled_Write_Cmd(0xFF);//--128
- Oled_Write_Cmd(0xA1);//set segment remap
- Oled_Write_Cmd(0xA6);//--normal / reverse
- Oled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
- Oled_Write_Cmd(0x3F);//--1/32 duty
- Oled_Write_Cmd(0xC8);//Com scan direction
- Oled_Write_Cmd(0xD3);//-set display offset
- Oled_Write_Cmd(0x00);//
-
- Oled_Write_Cmd(0xD5);//set osc division
- Oled_Write_Cmd(0x80);//
-
- Oled_Write_Cmd(0xD8);//set area color mode off
- Oled_Write_Cmd(0x05);//
-
- Oled_Write_Cmd(0xD9);//Set Pre-Charge Period
- Oled_Write_Cmd(0xF1);//
-
- Oled_Write_Cmd(0xDA);//set com pin configuartion
- Oled_Write_Cmd(0x12);//
-
- Oled_Write_Cmd(0xDB);//set Vcomh
- Oled_Write_Cmd(0x30);//
-
- Oled_Write_Cmd(0x8D);//set charge pump enable
- Oled_Write_Cmd(0x14);//
-
- Oled_Write_Cmd(0xAF);//--turn on oled panel
- }
-
- void Oled_Clear()
- {
- unsigned char i,j; //-128 --- 127
-
- for(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,每写入数据,列地址自动偏移
- for(j = 0;j<128;j++){
- Oled_Write_Data(0);
- }
- }
- }
-
- void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2
- unsigned int i;
- Oled_Write_Cmd(0xb0+(row*2-2)); //page 0
- Oled_Write_Cmd(0x00+(col&0x0f)); //low
- Oled_Write_Cmd(0x10+(col>>4)); //high
- for(i=((oledChar-32)*16);i<((oledChar-32)*16+8);i++){
- Oled_Write_Data(F8X16[i]); //写数据oledTable1
- }
-
- Oled_Write_Cmd(0xb0+(row*2-1)); //page 1
- Oled_Write_Cmd(0x00+(col&0x0f)); //low
- Oled_Write_Cmd(0x10+(col>>4)); //high
- for(i=((oledChar-32)*16+8);i<((oledChar-32)*16+8+8);i++){
- Oled_Write_Data(F8X16[i]); //写数据oledTable1
- }
- }
-
-
- /******************************************************************************/
- // 函数名称:Oled_Show_Char
- // 输入参数:oledChar
- // 输出参数:无
- // 函数功能:OLED显示单个字符
- /******************************************************************************/
- void Oled_Show_Str(char row,char col,char *str){
- while(*str!=0){
- Oled_Show_Char(row,col,*str);
- str++;
- col += 8;
- }
- }
-
-
-
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。