STM32
直播中

安立路

8年用户 787经验值
私信 关注
[问答]

如何去实现一种基于STM32的超声波避障小车代码呢

如何去实现一种基于STM32的超声波避障小车代码呢?超声波避障代码有有哪些呢?

回帖(1)

周臻庸

2021-11-26 09:12:50
超声波避障代码

#include "sys.h"       
#include "delay.h"       


#define EN1 PAout(2)                          //L293D控制管脚定义
#define IN1 PAout(3)                          //L293D控制管脚定义
#define IN2 PAout(4)                          //L293D控制管脚定义
#define EN2 PAout(7)                          //L293D控制管脚定义
#define IN3 PAout(6)                          //L293D控制管脚定义
#define IN4 PAout(5)                          //L293D控制管脚定义


#define BEEP PBout(5)                         //蜂鸣器控制管脚定义


#define KEY1 PAin(8)                                      //功能按键对应的管脚


#define BZ_LEFT PAin(13)                      //左边避障信号           
#define BZ_RIGHT PAin(14)                     //右边避障信号


#define ControlPort PAout(0)                  //舵机控制接口


#define Stop  0                               //舵机停标志
#define Right 1                                      //舵机右转标志
#define Left  2                                      //舵机左转标志


#define OLED_RST_Clr() PCout(13)=0            //RST
#define OLED_RST_Set() PCout(13)=1            //RST


#define OLED_RS_Clr() PBout(4)=0              //DC
#define OLED_RS_Set() PBout(4)=1              //DC


#define OLED_SCLK_Clr() PCout(15)=0           //SCL
#define OLED_SCLK_Set() PCout(15)=1           //SCL


#define OLED_SDIN_Clr() PCout(14)=0           //SDA
#define OLED_SDIN_Set() PCout(14)=1           //SDA


#define OLED_CMD  0                                  //写命令
#define OLED_DATA 1                                  //写数据


u32 JuLi;                                     //超声波测距


u8 pwmval_left  = 0;                          //左电机调速变量
u8 pwmval_right = 0;                          //右电机调速变量


u8 pwmval_left_init  = 6;                     //左电机速度值  
u8 pwmval_right_init = 6;                     //右电机速度值


u8 right_pwm = 1;                                    //左电机调速开关   
u8 left_pwm  = 1;                                                //右电机调速开关      


u8 TimeOutCounter = 0;
u8 LeftOrRight    = 0;
u16 timer = 0;   


u8 hw_flag;
u32 S_temp;


u8 OLED_GRAM[128][8];


const unsigned char oled_asc2_1206[95][12]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x3F,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x40,0x00,0x00,0x00},/*""",2*/
{0x09,0x00,0x0B,0xC0,0x3D,0x00,0x0B,0xC0,0x3D,0x00,0x09,0x00},/*"#",3*/
{0x18,0xC0,0x24,0x40,0x7F,0xE0,0x22,0x40,0x31,0x80,0x00,0x00},/*"$",4*/
{0x18,0x00,0x24,0xC0,0x1B,0x00,0x0D,0x80,0x32,0x40,0x01,0x80},/*"%",5*/
{0x03,0x80,0x1C,0x40,0x27,0x40,0x1C,0x80,0x07,0x40,0x00,0x40},/*"&",6*/
{0x10,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x20,0x40,0x40,0x20},/*"(",8*/
{0x00,0x00,0x40,0x20,0x20,0x40,0x1F,0x80,0x00,0x00,0x00,0x00},/*")",9*/
{0x09,0x00,0x06,0x00,0x1F,0x80,0x06,0x00,0x09,0x00,0x00,0x00},/*"*",10*/
{0x04,0x00,0x04,0x00,0x3F,0x80,0x04,0x00,0x04,0x00,0x00,0x00},/*"+",11*/
{0x00,0x10,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00},/*"-",13*/
{0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x20,0x01,0xC0,0x06,0x00,0x38,0x00,0x40,0x00,0x00,0x00},/*"/",15*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"0",16*/
{0x00,0x00,0x10,0x40,0x3F,0xC0,0x00,0x40,0x00,0x00,0x00,0x00},/*"1",17*/
{0x18,0xC0,0x21,0x40,0x22,0x40,0x24,0x40,0x18,0x40,0x00,0x00},/*"2",18*/
{0x10,0x80,0x20,0x40,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"3",19*/
{0x02,0x00,0x0D,0x00,0x11,0x00,0x3F,0xC0,0x01,0x40,0x00,0x00},/*"4",20*/
{0x3C,0x80,0x24,0x40,0x24,0x40,0x24,0x40,0x23,0x80,0x00,0x00},/*"5",21*/
{0x1F,0x80,0x24,0x40,0x24,0x40,0x34,0x40,0x03,0x80,0x00,0x00},/*"6",22*/
{0x30,0x00,0x20,0x00,0x27,0xC0,0x38,0x00,0x20,0x00,0x00,0x00},/*"7",23*/
{0x1B,0x80,0x24,0x40,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"8",24*/
{0x1C,0x00,0x22,0xC0,0x22,0x40,0x22,0x40,0x1F,0x80,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x08,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x04,0x60,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0x40,0x40},/*"<",28*/
{0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x00,0x00},/*"=",29*/
{0x00,0x00,0x40,0x40,0x20,0x80,0x11,0x00,0x0A,0x00,0x04,0x00},/*">",30*/
{0x18,0x00,0x20,0x00,0x23,0x40,0x24,0x00,0x18,0x00,0x00,0x00},/*"?",31*/
{0x1F,0x80,0x20,0x40,0x27,0x40,0x29,0x40,0x1F,0x40,0x00,0x00},/*"@",32*/
{0x00,0x40,0x07,0xC0,0x39,0x00,0x0F,0x00,0x01,0xC0,0x00,0x40},/*"A",33*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"B",34*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x30,0x80,0x00,0x00},/*"C",35*/
{0x20,0x40,0x3F,0xC0,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"D",36*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x2E,0x40,0x30,0xC0,0x00,0x00},/*"E",37*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x2E,0x00,0x30,0x00,0x00,0x00},/*"F",38*/
{0x0F,0x00,0x10,0x80,0x20,0x40,0x22,0x40,0x33,0x80,0x02,0x00},/*"G",39*/
{0x20,0x40,0x3F,0xC0,0x04,0x00,0x04,0x00,0x3F,0xC0,0x20,0x40},/*"H",40*/
{0x20,0x40,0x20,0x40,0x3F,0xC0,0x20,0x40,0x20,0x40,0x00,0x00},/*"I",41*/
{0x00,0x60,0x20,0x20,0x20,0x20,0x3F,0xC0,0x20,0x00,0x20,0x00},/*"J",42*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x0B,0x00,0x30,0xC0,0x20,0x40},/*"K",43*/
{0x20,0x40,0x3F,0xC0,0x20,0x40,0x00,0x40,0x00,0x40,0x00,0xC0},/*"L",44*/
{0x3F,0xC0,0x3C,0x00,0x03,0xC0,0x3C,0x00,0x3F,0xC0,0x00,0x00},/*"M",45*/
{0x20,0x40,0x3F,0xC0,0x0C,0x40,0x23,0x00,0x3F,0xC0,0x20,0x00},/*"N",46*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"O",47*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x24,0x00,0x18,0x00,0x00,0x00},/*"P",48*/
{0x1F,0x80,0x21,0x40,0x21,0x40,0x20,0xE0,0x1F,0xA0,0x00,0x00},/*"Q",49*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x26,0x00,0x19,0xC0,0x00,0x40},/*"R",50*/
{0x18,0xC0,0x24,0x40,0x24,0x40,0x22,0x40,0x31,0x80,0x00,0x00},/*"S",51*/
{0x30,0x00,0x20,0x40,0x3F,0xC0,0x20,0x40,0x30,0x00,0x00,0x00},/*"T",52*/
{0x20,0x00,0x3F,0x80,0x00,0x40,0x00,0x40,0x3F,0x80,0x20,0x00},/*"U",53*/
{0x20,0x00,0x3E,0x00,0x01,0xC0,0x07,0x00,0x38,0x00,0x20,0x00},/*"V",54*/
{0x38,0x00,0x07,0xC0,0x3C,0x00,0x07,0xC0,0x38,0x00,0x00,0x00},/*"W",55*/
{0x20,0x40,0x39,0xC0,0x06,0x00,0x39,0xC0,0x20,0x40,0x00,0x00},/*"X",56*/
{0x20,0x00,0x38,0x40,0x07,0xC0,0x38,0x40,0x20,0x00,0x00,0x00},/*"Y",57*/
{0x30,0x40,0x21,0xC0,0x26,0x40,0x38,0x40,0x20,0xC0,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x7F,0xE0,0x40,0x20,0x40,0x20,0x00,0x00},/*"[",59*/
{0x00,0x00,0x70,0x00,0x0C,0x00,0x03,0x80,0x00,0x40,0x00,0x00},/*"",60*/
{0x00,0x00,0x40,0x20,0x40,0x20,0x7F,0xE0,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x20,0x00,0x40,0x00,0x20,0x00,0x00,0x00,0x00,0x00},/*"^",62*/
{0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10},/*"_",63*/
{0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x02,0x80,0x05,0x40,0x05,0x40,0x03,0xC0,0x00,0x40},/*"a",65*/
{0x20,0x00,0x3F,0xC0,0x04,0x40,0x04,0x40,0x03,0x80,0x00,0x00},/*"b",66*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x06,0x40,0x00,0x00},/*"c",67*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x24,0x40,0x3F,0xC0,0x00,0x40},/*"d",68*/
{0x00,0x00,0x03,0x80,0x05,0x40,0x05,0x40,0x03,0x40,0x00,0x00},/*"e",69*/
{0x00,0x00,0x04,0x40,0x1F,0xC0,0x24,0x40,0x24,0x40,0x20,0x00},/*"f",70*/
{0x00,0x00,0x02,0xE0,0x05,0x50,0x05,0x50,0x06,0x50,0x04,0x20},/*"g",71*/
{0x20,0x40,0x3F,0xC0,0x04,0x40,0x04,0x00,0x03,0xC0,0x00,0x40},/*"h",72*/
{0x00,0x00,0x04,0x40,0x27,0xC0,0x00,0x40,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x10,0x00,0x10,0x04,0x10,0x27,0xE0,0x00,0x00,0x00,0x00},/*"j",74*/
{0x20,0x40,0x3F,0xC0,0x01,0x40,0x07,0x00,0x04,0xC0,0x04,0x40},/*"k",75*/
{0x20,0x40,0x20,0x40,0x3F,0xC0,0x00,0x40,0x00,0x40,0x00,0x00},/*"l",76*/
{0x07,0xC0,0x04,0x00,0x07,0xC0,0x04,0x00,0x03,0xC0,0x00,0x00},/*"m",77*/
{0x04,0x40,0x07,0xC0,0x04,0x40,0x04,0x00,0x03,0xC0,0x00,0x40},/*"n",78*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x03,0x80,0x00,0x00},/*"o",79*/
{0x04,0x10,0x07,0xF0,0x04,0x50,0x04,0x40,0x03,0x80,0x00,0x00},/*"p",80*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x50,0x07,0xF0,0x00,0x10},/*"q",81*/
{0x04,0x40,0x07,0xC0,0x02,0x40,0x04,0x00,0x04,0x00,0x00,0x00},/*"r",82*/
{0x00,0x00,0x06,0x40,0x05,0x40,0x05,0x40,0x04,0xC0,0x00,0x00},/*"s",83*/
{0x00,0x00,0x04,0x00,0x1F,0x80,0x04,0x40,0x00,0x40,0x00,0x00},/*"t",84*/
{0x04,0x00,0x07,0x80,0x00,0x40,0x04,0x40,0x07,0xC0,0x00,0x40},/*"u",85*/
{0x04,0x00,0x07,0x00,0x04,0xC0,0x01,0x80,0x06,0x00,0x04,0x00},/*"v",86*/
{0x06,0x00,0x01,0xC0,0x07,0x00,0x01,0xC0,0x06,0x00,0x00,0x00},/*"w",87*/
{0x04,0x40,0x06,0xC0,0x01,0x00,0x06,0xC0,0x04,0x40,0x00,0x00},/*"x",88*/
{0x04,0x10,0x07,0x10,0x04,0xE0,0x01,0x80,0x06,0x00,0x04,0x00},/*"y",89*/
{0x00,0x00,0x04,0x40,0x05,0xC0,0x06,0x40,0x04,0x40,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x04,0x00,0x7B,0xE0,0x40,0x20,0x00,0x00},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x40,0x20,0x7B,0xE0,0x04,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x40,0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x40,0x00},/*"~",94*/
};
const unsigned char oled_asc2_1608[95][16]={          
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xCC,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x08,0x00,0x30,0x00,0x60,0x00,0x08,0x00,0x30,0x00,0x60,0x00,0x00,0x00},/*""",2*/
{0x02,0x20,0x03,0xFC,0x1E,0x20,0x02,0x20,0x03,0xFC,0x1E,0x20,0x02,0x20,0x00,0x00},/*"#",3*/
{0x00,0x00,0x0E,0x18,0x11,0x04,0x3F,0xFF,0x10,0x84,0x0C,0x78,0x00,0x00,0x00,0x00},/*"$",4*/
{0x0F,0x00,0x10,0x84,0x0F,0x38,0x00,0xC0,0x07,0x78,0x18,0x84,0x00,0x78,0x00,0x00},/*"%",5*/
{0x00,0x78,0x0F,0x84,0x10,0xC4,0x11,0x24,0x0E,0x98,0x00,0xE4,0x00,0x84,0x00,0x08},/*"&",6*/
{0x08,0x00,0x68,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x18,0x18,0x20,0x04,0x40,0x02,0x00,0x00},/*"(",8*/
{0x00,0x00,0x40,0x02,0x20,0x04,0x18,0x18,0x07,0xE0,0x00,0x00,0x00,0x00,0x00,0x00},/*")",9*/
{0x02,0x40,0x02,0x40,0x01,0x80,0x0F,0xF0,0x01,0x80,0x02,0x40,0x02,0x40,0x00,0x00},/*"*",10*/
{0x00,0x80,0x00,0x80,0x00,0x80,0x0F,0xF8,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00},/*"+",11*/
{0x00,0x01,0x00,0x0D,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80},/*"-",13*/
{0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x00,0x00,0x06,0x00,0x18,0x00,0x60,0x01,0x80,0x06,0x00,0x18,0x00,0x20,0x00},/*"/",15*/
{0x00,0x00,0x07,0xF0,0x08,0x08,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"0",16*/
{0x00,0x00,0x08,0x04,0x08,0x04,0x1F,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"1",17*/
{0x00,0x00,0x0E,0x0C,0x10,0x14,0x10,0x24,0x10,0x44,0x11,0x84,0x0E,0x0C,0x00,0x00},/*"2",18*/
{0x00,0x00,0x0C,0x18,0x10,0x04,0x11,0x04,0x11,0x04,0x12,0x88,0x0C,0x70,0x00,0x00},/*"3",19*/
{0x00,0x00,0x00,0xE0,0x03,0x20,0x04,0x24,0x08,0x24,0x1F,0xFC,0x00,0x24,0x00,0x00},/*"4",20*/
{0x00,0x00,0x1F,0x98,0x10,0x84,0x11,0x04,0x11,0x04,0x10,0x88,0x10,0x70,0x00,0x00},/*"5",21*/
{0x00,0x00,0x07,0xF0,0x08,0x88,0x11,0x04,0x11,0x04,0x18,0x88,0x00,0x70,0x00,0x00},/*"6",22*/
{0x00,0x00,0x1C,0x00,0x10,0x00,0x10,0xFC,0x13,0x00,0x1C,0x00,0x10,0x00,0x00,0x00},/*"7",23*/
{0x00,0x00,0x0E,0x38,0x11,0x44,0x10,0x84,0x10,0x84,0x11,0x44,0x0E,0x38,0x00,0x00},/*"8",24*/
{0x00,0x00,0x07,0x00,0x08,0x8C,0x10,0x44,0x10,0x44,0x08,0x88,0x07,0xF0,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x03,0x0C,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x00,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x08,0x08,0x10,0x04,0x00,0x00},/*"<",28*/
{0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x02,0x20,0x00,0x00},/*"=",29*/
{0x00,0x00,0x10,0x04,0x08,0x08,0x04,0x10,0x02,0x20,0x01,0x40,0x00,0x80,0x00,0x00},/*">",30*/
{0x00,0x00,0x0E,0x00,0x12,0x00,0x10,0x0C,0x10,0x6C,0x10,0x80,0x0F,0x00,0x00,0x00},/*"?",31*/
{0x03,0xE0,0x0C,0x18,0x13,0xE4,0x14,0x24,0x17,0xC4,0x08,0x28,0x07,0xD0,0x00,0x00},/*"@",32*/
{0x00,0x04,0x00,0x3C,0x03,0xC4,0x1C,0x40,0x07,0x40,0x00,0xE4,0x00,0x1C,0x00,0x04},/*"A",33*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x04,0x11,0x04,0x0E,0x88,0x00,0x70,0x00,0x00},/*"B",34*/
{0x03,0xE0,0x0C,0x18,0x10,0x04,0x10,0x04,0x10,0x04,0x10,0x08,0x1C,0x10,0x00,0x00},/*"C",35*/
{0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"D",36*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x04,0x17,0xC4,0x10,0x04,0x08,0x18,0x00,0x00},/*"E",37*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x00,0x17,0xC0,0x10,0x00,0x08,0x00,0x00,0x00},/*"F",38*/
{0x03,0xE0,0x0C,0x18,0x10,0x04,0x10,0x04,0x10,0x44,0x1C,0x78,0x00,0x40,0x00,0x00},/*"G",39*/
{0x10,0x04,0x1F,0xFC,0x10,0x84,0x00,0x80,0x00,0x80,0x10,0x84,0x1F,0xFC,0x10,0x04},/*"H",40*/
{0x00,0x00,0x10,0x04,0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x04,0x00,0x00,0x00,0x00},/*"I",41*/
{0x00,0x03,0x00,0x01,0x10,0x01,0x10,0x01,0x1F,0xFE,0x10,0x00,0x10,0x00,0x00,0x00},/*"J",42*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x03,0x80,0x14,0x64,0x18,0x1C,0x10,0x04,0x00,0x00},/*"K",43*/
{0x10,0x04,0x1F,0xFC,0x10,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x0C,0x00,0x00},/*"L",44*/
{0x10,0x04,0x1F,0xFC,0x1F,0x00,0x00,0xFC,0x1F,0x00,0x1F,0xFC,0x10,0x04,0x00,0x00},/*"M",45*/
{0x10,0x04,0x1F,0xFC,0x0C,0x04,0x03,0x00,0x00,0xE0,0x10,0x18,0x1F,0xFC,0x10,0x00},/*"N",46*/
{0x07,0xF0,0x08,0x08,0x10,0x04,0x10,0x04,0x10,0x04,0x08,0x08,0x07,0xF0,0x00,0x00},/*"O",47*/
{0x10,0x04,0x1F,0xFC,0x10,0x84,0x10,0x80,0x10,0x80,0x10,0x80,0x0F,0x00,0x00,0x00},/*"P",48*/
{0x07,0xF0,0x08,0x18,0x10,0x24,0x10,0x24,0x10,0x1C,0x08,0x0A,0x07,0xF2,0x00,0x00},/*"Q",49*/
{0x10,0x04,0x1F,0xFC,0x11,0x04,0x11,0x00,0x11,0xC0,0x11,0x30,0x0E,0x0C,0x00,0x04},/*"R",50*/
{0x00,0x00,0x0E,0x1C,0x11,0x04,0x10,0x84,0x10,0x84,0x10,0x44,0x1C,0x38,0x00,0x00},/*"S",51*/
{0x18,0x00,0x10,0x00,0x10,0x04,0x1F,0xFC,0x10,0x04,0x10,0x00,0x18,0x00,0x00,0x00},/*"T",52*/
{0x10,0x00,0x1F,0xF8,0x10,0x04,0x00,0x04,0x00,0x04,0x10,0x04,0x1F,0xF8,0x10,0x00},/*"U",53*/
{0x10,0x00,0x1E,0x00,0x11,0xE0,0x00,0x1C,0x00,0x70,0x13,0x80,0x1C,0x00,0x10,0x00},/*"V",54*/
{0x1F,0xC0,0x10,0x3C,0x00,0xE0,0x1F,0x00,0x00,0xE0,0x10,0x3C,0x1F,0xC0,0x00,0x00},/*"W",55*/
{0x10,0x04,0x18,0x0C,0x16,0x34,0x01,0xC0,0x01,0xC0,0x16,0x34,0x18,0x0C,0x10,0x04},/*"X",56*/
{0x10,0x00,0x1C,0x00,0x13,0x04,0x00,0xFC,0x13,0x04,0x1C,0x00,0x10,0x00,0x00,0x00},/*"Y",57*/
{0x08,0x04,0x10,0x1C,0x10,0x64,0x10,0x84,0x13,0x04,0x1C,0x04,0x10,0x18,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFE,0x40,0x02,0x40,0x02,0x40,0x02,0x00,0x00},/*"[",59*/
{0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x80,0x00,0x60,0x00,0x1C,0x00,0x03,0x00,0x00},/*"",60*/
{0x00,0x00,0x40,0x02,0x40,0x02,0x40,0x02,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x00,0x00,0x20,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x00,0x00},/*"^",62*/
{0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01},/*"_",63*/
{0x00,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x00,0x98,0x01,0x24,0x01,0x44,0x01,0x44,0x01,0x44,0x00,0xFC,0x00,0x04},/*"a",65*/
{0x10,0x00,0x1F,0xFC,0x00,0x88,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x70,0x00,0x00},/*"b",66*/
{0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x00},/*"c",67*/
{0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x11,0x08,0x1F,0xFC,0x00,0x04},/*"d",68*/
{0x00,0x00,0x00,0xF8,0x01,0x44,0x01,0x44,0x01,0x44,0x01,0x44,0x00,0xC8,0x00,0x00},/*"e",69*/
{0x00,0x00,0x01,0x04,0x01,0x04,0x0F,0xFC,0x11,0x04,0x11,0x04,0x11,0x00,0x18,0x00},/*"f",70*/
{0x00,0x00,0x00,0xD6,0x01,0x29,0x01,0x29,0x01,0x29,0x01,0xC9,0x01,0x06,0x00,0x00},/*"g",71*/
{0x10,0x04,0x1F,0xFC,0x00,0x84,0x01,0x00,0x01,0x00,0x01,0x04,0x00,0xFC,0x00,0x04},/*"h",72*/
{0x00,0x00,0x01,0x04,0x19,0x04,0x19,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x00,0x00,0x03,0x00,0x01,0x01,0x01,0x19,0x01,0x19,0xFE,0x00,0x00,0x00,0x00},/*"j",74*/
{0x10,0x04,0x1F,0xFC,0x00,0x24,0x00,0x40,0x01,0xB4,0x01,0x0C,0x01,0x04,0x00,0x00},/*"k",75*/
{0x00,0x00,0x10,0x04,0x10,0x04,0x1F,0xFC,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00},/*"l",76*/
{0x01,0x04,0x01,0xFC,0x01,0x04,0x01,0x00,0x01,0xFC,0x01,0x04,0x01,0x00,0x00,0xFC},/*"m",77*/
{0x01,0x04,0x01,0xFC,0x00,0x84,0x01,0x00,0x01,0x00,0x01,0x04,0x00,0xFC,0x00,0x04},/*"n",78*/
{0x00,0x00,0x00,0xF8,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x00,0xF8,0x00,0x00},/*"o",79*/
{0x01,0x01,0x01,0xFF,0x00,0x85,0x01,0x04,0x01,0x04,0x00,0x88,0x00,0x70,0x00,0x00},/*"p",80*/
{0x00,0x00,0x00,0x70,0x00,0x88,0x01,0x04,0x01,0x04,0x01,0x05,0x01,0xFF,0x00,0x01},/*"q",81*/
{0x01,0x04,0x01,0x04,0x01,0xFC,0x00,0x84,0x01,0x04,0x01,0x00,0x01,0x80,0x00,0x00},/*"r",82*/
{0x00,0x00,0x00,0xCC,0x01,0x24,0x01,0x24,0x01,0x24,0x01,0x24,0x01,0x98,0x00,0x00},/*"s",83*/
{0x00,0x00,0x01,0x00,0x01,0x00,0x07,0xF8,0x01,0x04,0x01,0x04,0x00,0x00,0x00,0x00},/*"t",84*/
{0x01,0x00,0x01,0xF8,0x00,0x04,0x00,0x04,0x00,0x04,0x01,0x08,0x01,0xFC,0x00,0x04},/*"u",85*/
{0x01,0x00,0x01,0x80,0x01,0x70,0x00,0x0C,0x00,0x10,0x01,0x60,0x01,0x80,0x01,0x00},/*"v",86*/
{0x01,0xF0,0x01,0x0C,0x00,0x30,0x01,0xC0,0x00,0x30,0x01,0x0C,0x01,0xF0,0x01,0x00},/*"w",87*/
{0x00,0x00,0x01,0x04,0x01,0x8C,0x00,0x74,0x01,0x70,0x01,0x8C,0x01,0x04,0x00,0x00},/*"x",88*/
{0x01,0x01,0x01,0x81,0x01,0x71,0x00,0x0E,0x00,0x18,0x01,0x60,0x01,0x80,0x01,0x00},/*"y",89*/
{0x00,0x00,0x01,0x84,0x01,0x0C,0x01,0x34,0x01,0x44,0x01,0x84,0x01,0x0C,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x3E,0xFC,0x40,0x02,0x40,0x02},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x40,0x02,0x40,0x02,0x3E,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x00,0x00,0x60,0x00,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x20,0x00},/*"~",94*/
};


void Motor_Init(void);                        //电机接口初始化
void forward(void);                           //小车前进控制函数
void back(void);                                                //小车后退控制函数
void left_turn(void);                                //向左转
void right_turn(void);                                    //向右转  
void stop(void);                                                //停车
void circle_left(void);                                    //原地向左转圈
void circle_right(void);                                         //原地向右转圈
void left_moto(void);                         //左电机调速函数
void right_moto(void);                        //右电机调速函数


void Timer1_Init(u16 arr,u16 psc);            //定时器1初始化函数
void Timer2_Init(u16 arr,u16 psc);            //定时器2初始化函数
void Timer3_Init(u16 arr,u16 psc);            //定时器3初始化函数


void Beep_Init(void);                         //蜂鸣器接口初始化
void Key_Init(void);                          //按键接口初始化函数
void Key_Scan(void);                          //按键1扫描函数
void Bz_Init(void);                           //红外避障信号接口初始化函数


void OLED_WR_Byte(u8 dat,u8 cmd);            
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Refresh_Gram(void);                                                                          
void Oled_Init(void);
void OLED_Clear(void);
void OLED_DrawPoint(u8 x,u8 y,u8 t);
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode);
void OLED_ShowNumber(u8 x,u8 y,u32 num,u8 len,u8 size);
void OLED_ShowString(u8 x,u8 y,const u8 *p);       


void Oled_Show(void);


void Dj_Init(void);
void ControlLeftOrRight(void);


void Hw_bz(void);


void process(void);
/****************************************************************
                          程序功能
将超声波模块、舵机安装好并连接好杜邦线。智能小车上电后,按下开发
板启动按键(靠近电源开关那个)小车开始避障碍运动。同时测到的距离
值会在OLED中显示出来。


接线说明:
电机驱动线:
开发板的PA2接小车底盘的M6
开发板的PA3接小车底盘的M5
开发板的PA4接小车底盘的M4
开发板的PA5接小车底盘的M3
开发板的PA6接小车底盘的M2
开发板的PA7接小车底盘的M1


超声波模块接线:
超声波模块的VCC接开发板的5V
超声波模块的GND接开发板的GND
超声波模块的Trig接开发板的PB1
超声波模块的Echo接开发板的PB0


舵机接线:
将舵机线接到小车底盘的舵机接口上(注意方向,舵机棕线是GND,红线是VCC,
橙线是信号线。它们分别对应小车底盘舵机接口上的GND,5V和S)。另外,舵机
的信号线需要一条单独的杜邦线连接到开发板的PA0。


电源线:
开发板的5V接小车底盘的5V
开发板的GND接小车底盘的GND


红外避障信号线:
开发板的PA13接小车底盘的H3
开发板的PA14接小车底盘的H4
(本实验采用红外避障作为超声波避障的辅助,所以红外避障信号线也要
连接)
****************************************************************/
int main(void)
{
u8 k;
       
Stm32_Clock_Init(9);                         //系统时钟设置
delay_init(72);                                    //延时初始化
JTAG_Set(JTAG_SWD_DISABLE);                  //关闭JTAG接口
JTAG_Set(SWD_ENABLE);                        //打开SWD接口
Oled_Init();                                 //OLED初始化  
Timer3_Init(0XFFFF,72-1);                          //超声波初始化
Timer1_Init(499,7199);
Motor_Init();                                                  //初始化与电机连接的硬件接口
Timer2_Init(25,719);                         //10Khz的计数频率,计数到9为1ms
Beep_Init();                                 //蜂鸣器接口初始化                                 
Key_Init();                                  //按键接口初始化
Bz_Init();                                   //红外避障信号接口初始化
Dj_Init();                                   //舵机控制接口初始化
       
ControlLeftOrRight();                        //舵机初始化


Key_Scan();                                  //按键扫描
       
while(1)                                               
{
  if(timer>=400)
  {
   timer = 0;


   Oled_Show();                               //oled显示提示信息
   S_temp = JuLi;                             //超声波模块测到的距离值
   Hw_bz();                                   //红外避障


   if((S_temp>=250)&&(hw_flag == 0))                      //如果不满足避障条件(超声波模块测到前方障碍物距离大于25厘米或红外避障感应到前方有障碍物)     
   {
          BEEP = 1;
          forward();                                //智能小车继续前进
   }
   else                                       //如果满足避障条件   
   {          
          BEEP = 0;                                 //蜂鸣器响
          stop();                                   //智能小车停下
          for(k=0;k<=8;k++)
    {
           delay_ms(1000);
    }
          BEEP = 1;                                 //蜂鸣器不响
          process();                                //避障处理
   }
  }  
  Oled_Show();                                //OLED显示信息
}         
}


void Dj_Init(void)                            //舵机控制接口初始化函数
{
RCC->APB2ENR|=1<<2;                          //使能PORTA口时钟
GPIOA->CRL&=0XFFFFFFF0;                      //PORTA.0 推挽输出
GPIOA->CRL|=0X00000003;
GPIOA->ODR|=1<<0;                            //输出1
}


void ControlLeftOrRight(void)                 //舵机自检函数
{
u8 i;

LeftOrRight    = Stop;                       //舵机停在中间
TimeOutCounter = 0;
for(i=0;i<=9;i++)
{
        delay_ms(1000);
}

LeftOrRight = Left;                          //舵机左边
TimeOutCounter = 0;
for(i=0;i<=9;i++)
{
        delay_ms(1000);
}


LeftOrRight = Right;                         //舵机右边
TimeOutCounter = 0;
for(i=0;i<=13;i++)
{
        delay_ms(1000);
}

LeftOrRight    = Stop;                       //舵机停在中间
TimeOutCounter = 0;
for(i=0;i<=9;i++)
{
        delay_ms(1000);
}
}


void Hw_bz(void)                              //红外避障函数
{
if((BZ_LEFT == 0)||(BZ_RIGHT == 0))                //如果左右两边任何一个红外避障模块感应到障碍物              
{
  hw_flag = 1;                                            //设置红外避障标志
}
else
{
  hw_flag = 0;                                //屏蔽红外避障标志
}                          
}


void Beep_Init(void)                          //蜂鸣器接口初始化
{
RCC->APB2ENR|=1<<3;                          //使能PORTB时钟
  
GPIOB->CRL&=0XFF0FFFFF;
GPIOB->CRL|=0X00300000;                      //PB5推挽输出
GPIOB->ODR|=1<<5;                            //PB5输出高       
}


void Bz_Init(void)
{
RCC->APB2ENR|=1<<2;                          //使能PORTA时钟                    
GPIOA->CRH&=0XFF0FFFFF;
GPIOA->CRH|=0X00800000;                      //PA13上拉输入
GPIOA->ODR|=1<<13;                           //PA13上拉       


GPIOA->CRH&=0XF0FFFFFF;
GPIOA->CRH|=0X08000000;                      //PA14上拉输入
GPIOA->ODR|=1<<14;                           //PA14上拉       
}


void Key_Init(void)
{
RCC->APB2ENR|=1<<2;                          //使能PORTA时钟                    
GPIOA->CRH&=0XFFFFFFF0;
GPIOA->CRH|=0X00000008;                      //PA8上拉输入
GPIOA->ODR|=1<<8;                            //PA8上拉       
}


void Key_Scan(void)                           //按键扫描函数
{
LOOP:if(KEY1==0)                                          //第一次判断是否有按键按下
      {
       delay_ms(5);
             if(KEY1==0)                                        //第二次判断是否有按键按下
       {
                    BEEP = 0;                                          //蜂鸣器响
                    while(KEY1 == 0);                     //等待按键松开
                    BEEP = 1;                                    //蜂鸣器不响
       }
             else
             {
              goto LOOP;                            //第一次判断时如果按键没有按下重新扫描
             }
      }
      else
      {
       goto LOOP;                                    //第二次判断时如果按键没有按下重新扫描
      }
}


void Motor_Init(void)
{
RCC->APB2ENR|=1<<2;                    //使能PORTA接口时钟
  
GPIOA->CRL&=0XFFFFF0FF;
GPIOA->CRL|=0X00000300;                //PA2推挽输出
GPIOA->ODR|=1<<2;                      //PA2输出高电平
       
GPIOA->CRL&=0XFFFF0FFF;
GPIOA->CRL|=0X00003000;                //PA3推挽输出
GPIOA->ODR|=1<<3;                      //PA3输出高电平
       
GPIOA->CRL&=0XFFF0FFFF;
GPIOA->CRL|=0X00030000;                //PA4推挽输出
GPIOA->ODR|=1<<4;                      //PA4输出高电平


GPIOA->CRL&=0XFF0FFFFF;
GPIOA->CRL|=0X00300000;                //PA5推挽输出
GPIOA->ODR|=1<<5;                      //PA5输出高电平
       
GPIOA->CRL&=0XF0FFFFFF;
GPIOA->CRL|=0X03000000;                //PA6推挽输出
GPIOA->ODR|=1<<6;                      //PA6输出高电平       


GPIOA->CRL&=0X0FFFFFFF;
GPIOA->CRL|=0X30000000;                //PA7推挽输出
GPIOA->ODR|=1<<7;                      //PA7输出高电平
}


void forward(void)                      //小车前进控制函数
{
IN1 = 1;
IN2 = 0;

IN3 = 1;
IN4 = 0;  
}


void back(void)                                            //小车后退控制函数
{
IN1 = 0;
IN2 = 1;

IN3 = 0;
IN4 = 1;
}


void left_turn(void)                          //向左转
{  
IN1 = 1;
IN2 = 0;


IN3 = 0;
IN4 = 0;
}


void right_turn(void)                                //向右转  
{
IN1 = 0;
IN2 = 0;

IN3 = 1;
IN4 = 0;   
}


void stop(void)                                            //停车
{
IN1 = 0;
IN2 = 0;   

IN3 = 0;
IN4 = 0;
}


void circle_left(void)                              //原地向左转圈
{
IN1 = 1;
IN2 = 0;

IN3 = 0;
IN4 = 1;
}


void circle_right(void)                                     //原地向右转圈
{
IN1 = 0;
IN2 = 1;   

IN3 = 1;
IN4 = 0;   
}


void left_moto(void)                    //左电机调速函数
{  
if(left_pwm)
{
  if(pwmval_left <= pwmval_left_init)
  {
   EN1 = 1;
  }
  else
  {
   EN1 = 0;
  }
  if(pwmval_left >= 20)
  {
   pwmval_left = 0;
  }
}
else   
{
  EN1 = 0;                     
}
}


void right_moto(void)                   //右电机调速函数
{
if(right_pwm)
{
  if(pwmval_right <= pwmval_right_init)                  
  {
   EN2 = 1;                                                           
  }
  else if(pwmval_right > pwmval_right_init)
  {
   EN2 = 0;
  }
  if(pwmval_right >= 20)
  {
   pwmval_right = 0;
  }
}
else   
{
  EN2 = 0;                                                      
}
}


void OLED_Refresh_Gram(void)
{
u8 i,n;                    
for(i=0;i<8;i++)  
{  
  OLED_WR_Byte (0xb0+i,OLED_CMD);       //设置页地址(0~7)
  OLED_WR_Byte (0x00,OLED_CMD);         //设置显示位置—列低地址
  OLED_WR_Byte (0x10,OLED_CMD);         //设置显示位置—列高地址   
  for(n=0;n<128;n++)
  {
   OLED_WR_Byte(OLED_GRAM[n],OLED_DATA);
  }
}   
}


void OLED_WR_Byte(u8 dat,u8 cmd)
{       
u8 i;                          
if(cmd)
{
  OLED_RS_Set();
}
else
{
  OLED_RS_Clr();
}                  
for(i=0;i<8;i++)
{                          
  OLED_SCLK_Clr();
  if(dat&0x80)
  {
   OLED_SDIN_Set();
  }
  else
  {
   OLED_SDIN_Clr();
  }
  OLED_SCLK_Set();
  dat<<=1;   
}                                                   
OLED_RS_Set();             
}


void OLED_Display_On(void)
{
OLED_WR_Byte(0X8D,OLED_CMD);            //SET DCDC命令
OLED_WR_Byte(0X14,OLED_CMD);            //DCDC ON
OLED_WR_Byte(0XAF,OLED_CMD);            //DISPLAY ON
}


void OLED_Display_Off(void)
{
OLED_WR_Byte(0X8D,OLED_CMD);            //SET DCDC命令
OLED_WR_Byte(0X10,OLED_CMD);            //DCDC OFF
OLED_WR_Byte(0XAE,OLED_CMD);            //DISPLAY OFF
}


void OLED_Clear(void)  
{  
u8 i,n;  
for(i=0;i<8;i++)for(n=0;n<128;n++)OLED_GRAM[n]=0X00;  
OLED_Refresh_Gram();                    //更新显示
}


void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
u8 pos,bx,temp=0;
if(x>127||y>63)return;                  //超出范围了.
pos=7-y/8;
bx=y%8;
temp=1<<(7-bx);
if(t)OLED_GRAM[x][pos]|=temp;
else OLED_GRAM[x][pos]&=~temp;            
}


void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
{                                  
u8 temp,t,t1;
u8 y0=y;
chr=chr-' ';                             //得到偏移后的值                                  
for(t=0;t {   
  if(size==12)                                              //调用1206字体
  {
   temp=oled_asc2_1206[chr][t];  
  }
  else                                                                               //调用1608字体
  {
   temp=oled_asc2_1608[chr][t];                  
  }                                  
  for(t1=0;t1<8;t1++)
  {
   if(temp&0x80)
   {
    OLED_DrawPoint(x,y,mode);
   }
   else
   {
    OLED_DrawPoint(x,y,!mode);
   }
   temp<<=1;
   y++;
   if((y-y0)==size)
   {
        y=y0;
        x++;
        break;
   }
  }           
}         
}


u32 oled_pow(u8 m,u8 n)
{
u32 result=1;         
while(n--)result*=m;   
return result;
}


void OLED_ShowNumber(u8 x,u8 y,u32 num,u8 len,u8 size)
{                
u8 t,temp;
u8 enshow=0;                                                  
for(t=0;t {
  temp=(num/oled_pow(10,len-t-1))%10;
  if(enshow==0&&t<(len-1))
  {
   if(temp==0)
   {
        OLED_ShowChar(x+(size/2)*t,y,' ',size,1);
    continue;
   }
   else
   {
    enshow=1;
   }                           
  }
  OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1);
}
}


void OLED_ShowString(u8 x,u8 y,const u8 *p)
{
#define MAX_CHAR_POSX 122
#define MAX_CHAR_POSY 58         
while(*p!='')
{      
  if(x>MAX_CHAR_POSX){x=0;y+=16;}
  if(y>MAX_CHAR_POSY){y=x=0;OLED_Clear();}
  OLED_ShowChar(x,y,*p,12,1);         
  x+=8;
  p++;
}  
}


void Oled_Init(void)
{                    
RCC->APB2ENR|=1<<3;                  //使能PORTB时钟                    
GPIOB->CRL&=0XFFF0FFFF;
GPIOB->CRL|=0X00020000;              //PB4 推挽输出   


RCC->APB2ENR|=1<<4;                         //使能PORTC时钟  
RCC->APB2ENR|=1<<0;                         //使能AFIO时钟       
GPIOC->CRH&=0X000FFFFF;                    //PC13,14,15设置成输出 2MHz 推挽输出   
GPIOC->CRH|=0X22200000;
PWR->CR|=1<<8;                              //取消备份区写保护
RCC->BDCR&=0xFFFFFFFE;                      //外部低俗振荡器关闭 PC14,PC15成为普通IO                
BKP->CR&=0xFFFFFFFE;                       //侵入检测TAMPER引脚作为通用IO口使用
PWR->CR&=0xFFFFFEFF;                        //备份区写保护


OLED_RST_Clr();
delay_ms(100);
OLED_RST_Set();
                                          
OLED_WR_Byte(0xAE,OLED_CMD);         //关闭显示
OLED_WR_Byte(0xD5,OLED_CMD);         //设置时钟分频因子,震荡频率
OLED_WR_Byte(80,OLED_CMD);           //[3:0],分频因子;[7:4],震荡频率
OLED_WR_Byte(0xA8,OLED_CMD);         //设置驱动路数
OLED_WR_Byte(0X3F,OLED_CMD);         //默认0X3F(1/64)
OLED_WR_Byte(0xD3,OLED_CMD);         //设置显示偏移
OLED_WR_Byte(0X00,OLED_CMD);         //默认为0


OLED_WR_Byte(0x40,OLED_CMD);         //设置显示开始行 [5:0],行数.
                                                                                                            
OLED_WR_Byte(0x8D,OLED_CMD);         //电荷泵设置
OLED_WR_Byte(0x14,OLED_CMD);         //bit2,开启/关闭
OLED_WR_Byte(0x20,OLED_CMD);         //设置内存地址模式
OLED_WR_Byte(0x02,OLED_CMD);         //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
OLED_WR_Byte(0xA1,OLED_CMD);         //段重定义设置,bit0:0,0->0;1,0->127;
OLED_WR_Byte(0xC0,OLED_CMD);         //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
OLED_WR_Byte(0xDA,OLED_CMD);         //设置COM硬件引脚配置
OLED_WR_Byte(0x12,OLED_CMD);         //[5:4]配置
                 
OLED_WR_Byte(0x81,OLED_CMD);         //对比度设置
OLED_WR_Byte(0xEF,OLED_CMD);         //1~255;默认0X7F (亮度设置,越大越亮)
OLED_WR_Byte(0xD9,OLED_CMD);         //设置预充电周期
OLED_WR_Byte(0xf1,OLED_CMD);         //[3:0],PHASE 1;[7:4],PHASE 2;
OLED_WR_Byte(0xDB,OLED_CMD);         //设置VCOMH 电压倍率
OLED_WR_Byte(0x30,OLED_CMD);         //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;


OLED_WR_Byte(0xA4,OLED_CMD);         //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
OLED_WR_Byte(0xA6,OLED_CMD);         //设置显示方式;bit0:1,反相显示;0,正常显示                                                              
OLED_WR_Byte(0xAF,OLED_CMD);         //开启显示         
OLED_Clear();
}


void Oled_Show(void)
{       
OLED_ShowString(20,10,"ChaoSB-TEST");                             

OLED_ShowString(0,30,"Distance:");
OLED_ShowNumber(80,30,(u16)JuLi,4,12);
OLED_ShowString(110,30,"mm");
       
OLED_Refresh_Gram();                                //刷新
}


void process(void)                            //避障处理函数
{
u8 j;
u8 p;
       
u32 S1_temp = 0;
u32 S2_temp = 0;
         
LeftOrRight    = Left;                       //舵机转到左边
TimeOutCounter = 0;
for(j=0;j<=9;j++)
{
        delay_ms(1000);
}


Oled_Show();                                 //显示障碍物距离信息
S1_temp = JuLi;                              //小车左边障碍物距离存在变量S1_temp中
  
LeftOrRight    = Right;                      //舵机转到右边
TimeOutCounter = 0;
for(j=0;j<=13;j++)
{
        delay_ms(1000);
}

Oled_Show();                                 //显示障碍物距离信息
S2_temp = JuLi;                                     //小车右边障碍物距离存在变量S2_temp中
       
LeftOrRight    = Stop;                       //舵机回到中间
TimeOutCounter = 0;
for(j=0;j<=9;j++)
{
        delay_ms(1000);
}


if((S1_temp<=200)||(S2_temp<=200))           //如果超声波模块测得左边或右边障碍物的距离小于20厘米
{
  back();                                                  //小车后退
  for(p=0;p<=10;p++)
  {
         delay_ms(1000);
  }
}
else
{
  back();                                                  //小车后退
  for(p=0;p<=8;p++)
  {
         delay_ms(1000);
  }   
}


stop();                                      //小车停下
for(p=0;p<=2;p++)
{
        delay_ms(1000);
}
                  
if(S1_temp>S2_temp)                                     //如果左边障碍物离小车远
{
  circle_left();                                    //小车向左转
  for(p=0;p<=2;p++)
  {
         delay_ms(1000);
  }
}                                     
else if(S1_temp {
  circle_right();                                         //小车向右转
  for(p=0;p<=2;p++)
  {
         delay_ms(1000);
  }
}
}


void Timer3_Init(u16 arr,u16 psc)       
{         
RCC->APB1ENR|=1<<1;           //TIM3时钟使能     
RCC->APB2ENR|=1<<3;                 //使能PORTB时钟            
GPIOB->CRL&=0XFFFFFF00;
GPIOB->CRL|=0X00000028;       //PB.0 输入 PB.1输出
       
TIM3->ARR=arr;                             //设定计数器自动重装值   
TIM3->PSC=psc;                             //预分频器
TIM3->CCMR2|=1<<0;                   //选择输入端
TIM3->CCMR2|=0<<4;                  //配置输入滤波器 不滤波
TIM3->CCMR2|=0<<2;                  //配置输入分频,不分频


TIM3->CCER|=0<<9;                    //上升沿捕获
TIM3->CCER|=1<<8;                    //允许捕获计数器的值到捕获寄存器中


TIM3->DIER|=1<<3;             //允许捕获中断                               
TIM3->DIER|=1<<0;             //允许更新中断       
TIM3->CR1|=0x01;              //使能定时器3
MY_NVIC_Init(1,3,TIM3_IRQChannel,1);
}


/**************************************************************************
函数功能:超声波接收回波函数
入口参数:无
返回  值:无
**************************************************************************/
u16 TIM3CH3_CAPTURE_STA,TIM3CH3_CAPTURE_VAL;
void Read_Distane(void)
{   
PBout(1)=1;
delay_us(15);
PBout(1)=0;       
if(TIM3CH3_CAPTURE_STA&0X80)               //成功捕获到了一次高电平
{
  JuLi=TIM3CH3_CAPTURE_STA&0X3F;
  JuLi*=65536;                                                            //溢出时间总和
  JuLi+=TIM3CH3_CAPTURE_VAL;                            //得到总的高电平时间
  JuLi=JuLi*170/1000;
  TIM3CH3_CAPTURE_STA=0;                                      //开启下一次捕获
}                               
}


/**************************************************************************
函数功能:超声波回波脉宽读取中断
入口参数:无
返回  值:无
**************************************************************************/
void TIM3_IRQHandler(void)
{                                                                   
u16 tsr;
tsr=TIM3->SR;
if((TIM3CH3_CAPTURE_STA&0X80)==0)           //还未成功捕获       
{
  if(tsr&0X01)                               //溢出
  {            
   if(TIM3CH3_CAPTURE_STA&0X40)              //已经捕获到高电平了
   {
          if((TIM3CH3_CAPTURE_STA&0X3F)==0X3F)     //高电平太长了
          {
           TIM3CH3_CAPTURE_STA|=0X80;              //标记成功捕获了一次
           TIM3CH3_CAPTURE_VAL=0XFFFF;
          }
          else
          {
           TIM3CH3_CAPTURE_STA++;
          }
   }         
  }
  if(tsr&0x08)                               //捕获3发生捕获事件
  {       
   if(TIM3CH3_CAPTURE_STA&0X40)                           //捕获到一个下降沿                
   {                                 
          TIM3CH3_CAPTURE_STA|=0X80;                           //标记成功捕获到一次高电平脉宽
          TIM3CH3_CAPTURE_VAL=TIM3->CCR3;                 //获取当前的捕获值.
          TIM3->CCER&=~(1<<9);                                       //CC1P=0 设置为上升沿捕获
   }
   else                                                                                       //还未开始,第一次捕获上升沿
   {
          TIM3CH3_CAPTURE_STA=0;                                     //清空
          TIM3CH3_CAPTURE_VAL=0;
          TIM3CH3_CAPTURE_STA|=0X40;                           //标记捕获到了上升沿
          TIM3->CNT=0;                                                           //计数器清空
          TIM3->CCER|=1<<9;                                                //CC1P=1 设置为下降沿捕获
   }                    
  }                                                                                   
}
TIM3->SR=0;                                 //清除中断标志位              
}


/**************************************************************************
函数功能:定时中断初始化
入口参数:arr:自动重装值  psc:时钟预分频数
返回  值:无
**************************************************************************/
void Timer1_Init(u16 arr,u16 psc)  
{  
RCC->APB2ENR|=1<<11;                       //TIM1时钟使能   
TIM1->ARR=arr;                             //设定计数器自动重装值   
TIM1->PSC=psc;                             //预分频器7200,得到10Khz的计数时钟
TIM1->DIER|=1<<0;                          //允许更新中断                               
TIM1->DIER|=1<<6;                          //允许触发中断          
TIM1->CR1|=0x01;                           //使能定时器
MY_NVIC_Init(1,3,TIM1_UP_IRQChannel,2);
}


/**************************************************************************
函数功能:定时中断初始化
入口参数:arr:自动重装值  psc:时钟预分频数
返回  值:无
**************************************************************************/
int TIM1_UP_IRQHandler(void)  
{   
if(TIM1->SR&0X0001)                    //5ms定时中断
{   
  TIM1->SR&=~(1<<0);                    //清除定时器1中断标志位                                       
}
Read_Distane();            
return 0;
}


//定时器3中断服务程序         
void TIM2_IRQHandler(void)
{                                                                   
if(TIM2->SR&0X0001)                          //溢出中断
{
  TimeOutCounter ++;
  timer++;


  switch(LeftOrRight)
  {
   case 0 :                                          //1.5ms
   {
    if(TimeOutCounter<=6)
    {
           ControlPort = 1;
    }
    else
    {               
     ControlPort = 0;
    }
   }break;


   case 1 :                                   //1ms
   {
    if(TimeOutCounter<=4)
    {
           ControlPort = 1;
    }
    else
    {
           ControlPort = 0;
    }               
   }break;


   case 2 :                                   //2ms
   {
    if(TimeOutCounter<=8)
    {
           ControlPort = 1;
    }
    else
    {
           ControlPort = 0;
    }                       
   }break;
   default : break;
  }


  if(TimeOutCounter <= 30)
  {
   EN1 = 1;
   EN2 = 1;
  }
  else if(TimeOutCounter > 30)
  {
   EN1 = 0;
   EN2 = 0;
  }
       
  if(TimeOutCounter==80)                            //20ms
  {
   TimeOutCounter = 0;
  }
}                                  
TIM2->SR&=~(1<<0);                           //清除中断标志位             
}


//通用定时器中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3
void Timer2_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<0;                    //TIM2时钟使能   
TIM2->ARR=arr;                         //设定计数器自动重装值//刚好1ms   
TIM2->PSC=psc;                         //预分频器7200,得到10Khz的计数时钟
//这两个东东要同时设置才可以使用中断
TIM2->DIER|=1<<0;                      //允许更新中断                                  
TIM2->CR1|=0x01;                       //使能定时器3
MY_NVIC_Init(1,3,TIM2_IRQChannel,2);   //抢占1,子优先级3,组2                                                                         
}
中断函数
#include "sys.h"
  
//设置向量表偏移地址
//NVIC_VectTab:基址
//Offset:偏移量
//CHECK OK
//091207
void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset)         
{
//检查参数合法性
assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
assert_param(IS_NVIC_OFFSET(Offset));           
SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80);             //设置NVIC的向量表偏移寄存器
//用于标识向量表是在CODE区还是在RAM区
}


//设置NVIC分组
//NVIC_Group:NVIC分组 0~4 总共5组
//CHECK OK
//091209
void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)         
{
u32 temp,temp1;          
temp1=(~NVIC_Group)&0x07;                                       //取后三位
temp1<<=8;
temp=SCB->AIRCR;                                                //读取先前的设置
temp&=0X0000F8FF;                                               //清空先前分组
temp|=0X05FA0000;                                               //写入钥匙
temp|=temp1;          
SCB->AIRCR=temp;                                                //设置分组                                                        
}


//设置NVIC
//NVIC_PreemptionPriority:抢占优先级
//NVIC_SubPriority       :响应优先级
//NVIC_Channel           :中断编号
//NVIC_Group             :中断分组 0~4
//注意优先级不能超过设定的组的范围!否则会有意想不到的错误
//组划分:
//组0:0位抢占优先级,4位响应优先级
//组1:1位抢占优先级,3位响应优先级
//组2:2位抢占优先级,2位响应优先级
//组3:3位抢占优先级,1位响应优先级
//组4:4位抢占优先级,0位响应优先级
//NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先
//CHECK OK
//100329
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)         
{
u32 temp;       
u8 IPRADDR=NVIC_Channel/4;                                    //每组只能存4个,得到组地址
u8 IPROFFSET=NVIC_Channel%4;                                  //在组内的偏移
IPROFFSET=IPROFFSET*8+4;                                      //得到偏移的确切位置
MY_NVIC_PriorityGroupConfig(NVIC_Group);                      //设置分组
temp=NVIC_PreemptionPriority<<(4-NVIC_Group);          
temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
temp&=0xf;                                                    //取低四位


if(NVIC_Channel<32)NVIC->ISER[0]|=1< else NVIC->ISER[1]|=1<<(NVIC_Channel-32);   
NVIC->IPR[IPRADDR]|=temp< }


//外部中断配置函数
//只针对GPIOA~G;不包括PVD,RTC和USB唤醒这三个
//参数:GPIOx:0~6,代表GPIOA~G;BITx:需要使能的位;TRIM:触发模式,1,下升沿;2,上降沿;3,任意电平触发
//该函数一次只能配置1个IO口,多个IO口,需多次调用
//该函数会自动开启对应中断,以及屏蔽线   
//待测试...
void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM)
{
u8 EXTADDR;
u8 EXTOFFSET;
EXTADDR=BITx/4;                                              //得到中断寄存器组的编号
EXTOFFSET=(BITx%4)*4;


RCC->APB2ENR|=0x01;                                          //使能io复用时钟


AFIO->EXTICR[EXTADDR]&=~(0x000F< AFIO->EXTICR[EXTADDR]|=GPIOx<        
//自动设置
EXTI->IMR|=1< if(TRIM&0x01)EXTI->FTSR|=1< if(TRIM&0x02)EXTI->RTSR|=1< }


//不能在这里执行所有外设复位!否则至少引起串口不工作.                    
//把所有时钟寄存器复位
//CHECK OK
//091209
void MYRCC_DeInit(void)
{                                                                                                                            
RCC->APB1RSTR = 0x00000000;//复位结束                         
RCC->APB2RSTR = 0x00000000;
          
RCC->AHBENR = 0x00000014;  //睡眠模式闪存和SRAM时钟使能.其他关闭.          
RCC->APB2ENR = 0x00000000; //外设时钟关闭.                          
RCC->APB1ENR = 0x00000000;   
RCC->CR |= 0x00000001;     //使能内部高速时钟HSION                                                                                                                                  
RCC->CFGR &= 0xF8FF0000;   //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0]                                         
RCC->CR &= 0xFEF6FFFF;     //复位HSEON,CSSON,PLLON
RCC->CR &= 0xFFFBFFFF;     //复位HSEBYP                     
RCC->CFGR &= 0xFF80FFFF;   //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE
RCC->CIR = 0x00000000;     //关闭所有中断

//配置向量表                                  
#ifdef  VECT_TAB_RAM
         MY_NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else   
         MY_NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
}


//THUMB指令不支持汇编内联
//采用如下方法实现执行汇编指令WFI
//CHECK OK
//091209
__asm void WFI_SET(void)
{
WFI;   
}


//进入待机模式         
//check ok
//091202
void Sys_Standby(void)
{
SCB->SCR|=1<<2;                 //使能SLEEPDEEP位 (SYS->CTRL)          
RCC->APB1ENR|=1<<28;            //使能电源时钟            
PWR->CSR|=1<<8;                 //设置WKUP用于唤醒
PWR->CR|=1<<2;                  //清除Wake-up 标志
PWR->CR|=1<<1;                  //PDDS置位                  
WFI_SET();                                               //执行WFI指令                 
}          
   
//系统软复位
//CHECK OK
//091209
void Sys_Soft_Reset(void)
{   
SCB->AIRCR =0X05FA0000|(u32)0x04;          
}


//JTAG模式设置,用于设置JTAG的模式
//mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭;
//CHECK OK       
//100818                  
void JTAG_Set(u8 mode)
{
u32 temp;
temp=mode;
temp<<=25;
RCC->APB2ENR|=1<<0;              //开启辅助时钟          
AFIO->MAPR&=0XF8FFFFFF;          //清除MAPR的[26:24]
AFIO->MAPR|=temp;                //设置jtag模式
}


//系统时钟初始化函数
//pll:选择的倍频数,从2开始,最大值为16       
//CHECK OK
//091209
void Stm32_Clock_Init(u8 PLL)
{
unsigned char temp=0;   
MYRCC_DeInit();                              //复位并配置向量表
RCC->CR|=0x00010000;             //外部高速时钟使能HSEON
while(!(RCC->CR>>17));           //等待外部时钟就绪
RCC->CFGR=0X00000400;            //APB1=DIV2;APB2=DIV1;AHB=DIV1;
PLL-=2;//抵消2个单位
RCC->CFGR|=PLL<<18;              //设置PLL值 2~16
RCC->CFGR|=1<<16;                      //PLLSRC ON
FLASH->ACR|=0x32;                      //FLASH 2个延时周期


RCC->CR|=0x01000000;             //PLLON
while(!(RCC->CR>>25));           //等待PLL锁定
RCC->CFGR|=0x00000002;           //PLL作为系统时钟         
while(temp!=0x02)                //等待PLL作为系统时钟设置成功
{   
        temp=RCC->CFGR>>2;
        temp&=0x03;
}   
}                    
延时函数
#include
#include
#include "delay.h"

static u8  fac_us=0;                     //us延时倍乘数
static u16 fac_ms=0;                     //ms延时倍乘数


//初始化延迟函数
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init(u8 SYSCLK)
{
SysTick->CTRL&=0xfffffffb;              //bit2清空,选择外部时钟  HCLK/8
fac_us=SYSCLK/8;                    
fac_ms=(u16)fac_us*1000;
}       


//延时nms
//注意nms的范围,nms<=1864
void delay_ms(u16 nms)
{                                     
u32 temp;                  
SysTick->LOAD=(u32)nms*fac_ms;         //时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00;                    //清空计数器
SysTick->CTRL=0x01 ;                   //开始倒数  
do
{
        temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16)));     //等待时间到达   
SysTick->CTRL=0x00;                    //关闭计数器
SysTick->VAL =0X00;                    //清空计数器                      
}   


//延时nus
//nus为要延时的us数.                                                                                      
void delay_us(u32 nus)
{               
u32 temp;                     
SysTick->LOAD=nus*fac_us;              //时间加载                           
SysTick->VAL=0x00;                     //清空计数器
SysTick->CTRL=0x01 ;                   //开始倒数          
do
{
        temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16)));     //等待时间到达   
SysTick->CTRL=0x00;                    //关闭计数器
SysTick->VAL =0X00;                    //清空计数器         
}


接线说明:
电机驱动线:
1、 开发板 PA2 接小车底盘 M6 2、 开发板 PA3 接小车底盘 M5
3、 开发板 PA4 接小车底盘 M4 4、 开发板 PA5 接小车底盘 M3
5、 开发板 PA6 接小车底盘 M2 6、 开发板 PA7 接小车底盘 M1
超声波模块接线:
1、超声波模块 VCC 接开发板 5V 2、超声波模块 GND 接开发板 GND
3、超声波模块 Trig 接开发板 PB1 4、超声波模块 Echo 接开发板 PB0
舵机接线:
将舵机线接到小车底盘的舵机接口上(注意方向, 舵机棕线是 GND,
红线是 VCC, 橙线是信号线。 它们分别对应小车底盘舵机接口上的
GND,5V 和 S)。 另外, 舵机的信号线需要一条单独的杜邦线连接到
开发板的 PA0。
电源线:
1、 开发板 5V 接小车底盘 5V 2、 开发板 GND 接小车底盘 GND
红外避障信号线:
1、 开发板 PA13 接小车底盘 H3 2、 开发板 PA14 接小车底盘 H4
![(本实验采用红外避障作为超声波避障的辅助, 所以红外避障信号线
也要连接)

小车底板电路图:



举报

更多回帖

×
20
完善资料,
赚取积分