1.简要逻辑
差不多就是这样了,有这样的逻辑写还是很简单的,无脑if
2.cubemx配置
首先配置打开编码器捕获的定时器
我这里打开了2,3,4,5定时器,做编码器捕获,中断优先级为0,最高
之后打开普通定时器6开启低于这4个编码器一级的中断,用于计算pid
还有开启定时器8打开4个pwm通道
接下来配置8个输出引脚给每个电机各两个,可自己设置,按我的来就不用改代码了
还有uart通讯口要打开
记得打开uart中断优先最高级0
还有oled的i2c
最后看所有的中断
3.uart通讯
openmvuar的引脚
接下来加入代码,为方便直接再main.c中插入
uint8_t USART1_RX_BUFF[USART1_REC_LENGTH];//接收缓冲,最大USART_REC_LEN个字节.
uint16_t USART1_RX_ST=0;//接收状态标记//bit15:接收完成标志,bit14~0:接收到的有效字节数目
uint8_t USART1_Data;//当前串口中断接收的1个字节数据的缓存
int cx,cy,cw,ch;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//串口中断回调函数
{
if(huart ==&huart1)
{
if((USART1_RX_ST&0x8000)==0)//接收未完成
{
if(USART1_Data==0x5B)//接收到了0x5A
{
USART1_RX_ST|=0x8000; //接收完成了,将USART1_RX_STA中的bit15(15位)置1
}
else
{
USART1_RX_BUFF[USART1_RX_ST&0X7FFF]=USART1_Data; //将收到的数据放入数组,
USART1_RX_ST++; //数据长度计数加1
if(USART1_RX_ST>(USART1_REC_LENGTH-1))USART1_RX_ST=0;//接收数据错误,重新开始接收
}
}
HAL_UART_Receive_IT(&huart1,(uint8_t *)&USART1_Data,1); //因为每执行完一次中断回调函数会将接收中断功能关闭,所以最后需要再开启接收中断
}
}
在main.h中插入
extern UART_HandleTypeDef huart1;//声明USART1的HAL库结构体
#define USART1_REC_LENGTH 200//定义USART1最大接收字节数
extern uint8_t USART1_RX_BUFF[USART1_REC_LENGTH];//接收缓冲,最大USART_REC_LEN个字节.末字节为校验和
extern uint16_t USART1_RX_ST;//接收状态标记
extern uint8_t USART1_Data;//当前串口中断接收的1个字节数据的缓存
extern int cx;
extern int cy;
extern int cw;
extern int ch;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);//串口中断回调函数声明
4.底盘pid
这个我之前的博客有写过单个电机的pid,没懂得可以先参考
单个编码器电机pid
我使用的底盘驱动是tb6612,能插上四个编码器电机
代码如下
pid.c
#include "pid.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "main.h"
#define Encoder_TIM_Handle2 htim2
#define Encoder_TIM_Handle3 htim3
#define Encoder_TIM_Handle4 htim4
#define Encoder_TIM_Handle5 htim5
#define Motor_MAX_Duty 2000
int a;
typedef struct __PID_Increment_Struct
{
float Kp, Ki, Kd; //系数
float Error_Last1; //上次误差
float Error_Last2; //上次误差
float Out_Last; //上次输出
} PID_Increment_Struct;
void motor11()//1正
{
AIN1(1);
AIN2(0);}
void motor10()//1反
{
AIN1(0);
AIN2(1);}
void motor21()//2正
{
BIN1(0);
BIN2(1);}
void motor20()//2反
{
BIN1(1);
BIN2(0);}
void motor31()//3正
{
CIN1(0);
CIN2(1);}
void motor30()//3反
{
CIN1(1);
CIN2(0);}
void motor40()//4正
{
DIN1(0);
DIN2(1);}
void motor41()//4反
{
DIN1(1);
DIN2(0);}
float Get_Speed1()
{
int16_t zj;
float Speed = 0;
zj = __HAL_TIM_GetCounter(&Encoder_TIM_Handle2);
__HAL_TIM_SetCounter(&Encoder_TIM_Handle2, 0);
Speed = (float)zj / (4 * 11 * 30) * 100 * 60;
a=Speed;
return Speed;
// printf("%f\n",Speed);//输出转速
}
float Get_Speed2()
{
int16_t zj;
float Speed = 0;
zj = __HAL_TIM_GetCounter(&Encoder_TIM_Handle3);
__HAL_TIM_SetCounter(&Encoder_TIM_Handle3, 0);
Speed = (float)zj / (4 * 11 * 30) * 100 * 60;
return Speed;
// printf("%f\n",Speed);//输出转速
}
float Get_Speed3()
{
int16_t zj;
float Speed = 0;
zj = __HAL_TIM_GetCounter(&Encoder_TIM_Handle4);
__HAL_TIM_SetCounter(&Encoder_TIM_Handle4, 0);
Speed = (float)zj / (4 * 11 * 30) * 100 * 60;
return Speed;
// printf("%f\n",Speed);//输出转速
}
float Get_Speed4()
{
int16_t zj;
float Speed = 0;
zj = __HAL_TIM_GetCounter(&Encoder_TIM_Handle5);
__HAL_TIM_SetCounter(&Encoder_TIM_Handle5, 0);
Speed = (float)zj / (4 * 11 * 30) * 100 * 60;
return Speed;
// printf("%f\n",Speed);//输出转速
}
float PID_Increment(PID_Increment_Struct *PID, float Current, float Target)
{
float err, //误差
out, //输出
proportion, //比例
differential; //微分
err = (float)Target - (float)Current; //计算误差
proportion = (float)err - (float)PID->Error_Last1; //计算比例项
differential = (float)err - 2 * (float)PID->Error_Last1 + (float)PID->Error_Last2; //计算微分项
if((err<=40&&err>=1)||(err<=-1&&err>=-40))
out = (float)PID->Out_Last + (float)PID->Kp * proportion+(float)PID->Ki * err+ (float)PID->Kd * differential; //计算PID
else //如果不if else,调试的时候如果单片机只是5v上电但电机没转,你接12v电源开电机,电机速度会拉满,这就不好了
out = (float)PID->Out_Last + (float)PID->Kp * proportion+(float)PID->Kd * differential; //计算PID
// out = (float)PID->Out_Last + (float)PID->Kp * proportion+(float)PID->Ki * err+ (float)PID->Ki * err + (float)PID->Kd * differential; //计算PID
PID->Error_Last2 = PID->Error_Last1; //更新上上次误差
PID->Error_Last1 = err; //更新误差
PID->Out_Last = out; //更新上此输出
return out;
}
void motor1(int16_t Speed)
{
if (Speed == 0)
{
__HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_1,Motor_MAX_Duty+1 );
}
else if (Speed > 0)
{
motor10();
__HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_1,Speed);
}
else if (Speed < 0)
{
Speed *= -1;
motor11();
__HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_1,Speed);
}
}
void motor2(int16_t Speed)
{
if (Speed == 0)
{
__HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_2,Motor_MAX_Duty+1 );
}
else if (Speed > 0)
{
motor20();
__HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_2,Speed);
}
else if (Speed < 0)
{
Speed *= -1;
motor21();
__HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_2,Speed);
}
}
void motor3(int16_t Speed)
{
if (Speed == 0)
{
__HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_3,Motor_MAX_Duty+1 );
}
else if (Speed > 0)
{
motor30();
__HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_3,Speed);
}
else if (Speed < 0)
{
Speed *= -1;
motor31();
__HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_3,Speed);
}
}
void motor4(int16_t Speed)
{
if (Speed == 0)
{
__HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_4,Motor_MAX_Duty+1 );
}
else if (Speed > 0)
{
motor40();
__HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_4,Speed);
}
else if (Speed < 0)
{
Speed *= -1;
motor41();
__HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_4,Speed);
}
}
PID_Increment_Struct PID_Speed = {5, 0, 0};
float Speed[4]={0,0,0,0};
float mb_speed_last;
float set_speed[4];
float mb_speed[4];
int i;
float mb_speed[4];
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
// float Speed = 0;
// float set_speed = 0;
float s=cw*ch;
if (htim == &htim2)
{
}
else if (htim == &htim3)
{
}
else if (htim == &htim4)
{
}
else if (htim == &htim5)
{
}
else if (htim == &htim6)
{
Speed[0] = Get_Speed1();
Speed[1] = Get_Speed2();
Speed[2] = Get_Speed3();
Speed[3] = Get_Speed4();
// mb_speed = (int16_t)PID_Increment(&PID_Speed, Speed , aa);
if(cw>=10&&ch>=10)
{mb_speed[0] = 0.012*(9000-s)-(162-cx);
mb_speed[1] = 0.012*(9000-s)+(162-cx);
mb_speed[2] = 0.012*(9000-s)+(162-cx);
mb_speed[3] = 0.012*(9000-s)-(162-cx);}
else
{mb_speed[0] = 50;
mb_speed[1] = -50;
mb_speed[2] = -50;
mb_speed[3] = 50;}
for(i=0;i<4;i++)
{set_speed[i] = PID_Increment(&PID_Speed, Speed[i], mb_speed[i]);
if (set_speed[i]> 2000)
set_speed[i] = 2000;
else if (set_speed[i] < -2000)
set_speed[i] = -2000;
}
motor1(set_speed[0]);
motor2(set_speed[1]);
motor3(set_speed[2]);
motor4(set_speed[3]);
// printf("%f,%f\r\n", Speed, mb_speed);
// a=set_speed;
// printf("%f,%f\r\n", angle, Speed);
}
}
pid.h
#ifndef __PID_H
#define __PID_H
#define AIN1(state) HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,(GPIO_PinState)(state)) //IN1
#define AIN2(state) HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,(GPIO_PinState)(state)) //IN2
#define BIN1(state) HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,(GPIO_PinState)(state)) //IN1
#define BIN2(state) HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,(GPIO_PinState)(state)) //IN2
#define CIN1(state) HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4,(GPIO_PinState)(state)) //IN1
#define CIN2(state) HAL_GPIO_WritePin(GPIOC,GPIO_PIN_5,(GPIO_PinState)(state)) //IN2
#define DIN1(state) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,(GPIO_PinState)(state)) //IN1
#define DIN2(state) HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,(GPIO_PinState)(state)) //IN2
extern int a;
#endif
5.oled
具体学习可以参考链接: link
oled.c
/*
* oled.c
*
* Created on: 2022年7月24日
* Author: Unicorn_Li
*/
#include "oled.h"
/**********************************************************
* 初始化命令,根据芯片手册书写,详细步骤见上图以及注意事项
***********************************************************/
uint8_t CMD_Data[]={
0xAE, 0xD5, 0x80, 0xA8, 0x3F, 0xD3, 0x00, 0x40,0xA1, 0xC8, 0xDA,
0x12, 0x81, 0xCF, 0xD9, 0xF1, 0xDB, 0x40, 0xA4, 0xA6,0x8D, 0x14,
0xAF};
/**
* @function: void OLED_Init(void)
* @description: OLED初始化
* @return {*}
*/
void OLED_Init(void)
{
HAL_Delay(200);
uint8_t i = 0;
for(i=0; i<23; i++)
{
OLED_WR_CMD(CMD_Data[i]);
}
}
/**
* @function: void OLED_WR_CMD(uint8_t cmd)
* @description: 向设备写控制命令
* @param {uint8_t} cmd 芯片手册规定的命令
* @return {*}
*/
void OLED_WR_CMD(uint8_t cmd)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&cmd,1,0x100);
}
/**
* @function: void OLED_WR_DATA(uint8_t data)
* @description: 向设备写控制数据
* @param {uint8_t} data 数据
* @return {*}
*/
void OLED_WR_DATA(uint8_t data)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&data,1,0x100);
}
/**
* @function: void OLED_On(void)
* @description: 更新显示
* @return {*}
*/
void OLED_On(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i); //设置页地址(0~7)
OLED_WR_CMD(0x00); //设置显示位置—列低地址
OLED_WR_CMD(0x10); //设置显示位置—列高地址
for(n=0;n<128;n++)
OLED_WR_DATA(1);
}
}
/**
* @function: OLED_Clear(void)
* @description: 清屏,整个屏幕是黑色的!和没点亮一样!!!
* @return {*}
*/
void OLED_Clear(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i); //设置页地址(0~7)
OLED_WR_CMD(0x00); //设置显示位置—列低地址
OLED_WR_CMD(0x10); //设置显示位置—列高地址
for(n=0;n<128;n++)
OLED_WR_DATA(0);
}
}
/**
* @function: void OLED_Display_On(void)
* @description: 开启OLED显示
* @return {*}
*/
void OLED_Display_On(void)
{
OLED_WR_CMD(0X8D); //SET DCDC命令
OLED_WR_CMD(0X14); //DCDC ON
OLED_WR_CMD(0XAF); //DISPLAY ON,打开显示
}
/**
* @function: void OLED_Display_Off(void)
* @description: 关闭OLED显示
* @return {*}
*/
void OLED_Display_Off(void)
{
OLED_WR_CMD(0X8D); //SET DCDC命令
OLED_WR_CMD(0X10); //DCDC OFF
OLED_WR_CMD(0XAE); //DISPLAY OFF,关闭显示
}
/**
* @function: void OLED_Set_Pos(uint8_t x, uint8_t y)
* @description: 坐标设置
* @param {uint8_t} x,y
* @return {*}
*/
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
OLED_WR_CMD(0xb0+y); //设置页地址(0~7)
OLED_WR_CMD(((x&0xf0)>>4)|0x10); //设置显示位置—列高地址
OLED_WR_CMD(x&0x0f); //设置显示位置—列低地址
}
/**
* @function: unsigned int oled_pow(uint8_t m,uint8_t n)
* @description: m^n函数
* @param {uint8_t} m,n
* @return {unsigned int} result
*/
unsigned int oled_pow(uint8_t m,uint8_t n)
{
unsigned int result=1;
while(n--)result*=m;
return result;
}
/**
* @function: void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t Char_Size,uint8_t Color_Turn)
* @description: 在OLED12864特定位置开始显示一个字符
* @param {uint8_t} x字符开始显示的横坐标
* @param {uint8_t} y字符开始显示的纵坐标
* @param {uint8_t} chr待显示的字符
* @param {uint8_t} Char_Size待显示字符的字体大小,选择字体 16/12
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size,uint8_t Color_Turn)
{
unsigned char c=0,i=0;
c=chr-' ';//得到偏移后的值
if(x>128-1){x=0;y=y+2;}
if(Char_Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
{
if(Color_Turn)
OLED_WR_DATA(~F8X16[c*16+i]);
else
OLED_WR_DATA(F8X16[c*16+i]);
}
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
{
if(Color_Turn)
OLED_WR_DATA(~F8X16[c*16+i+8]);
else
OLED_WR_DATA(F8X16[c*16+i+8]);
}
}
else
{
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
{
if(Color_Turn)
OLED_WR_DATA(~F6x8[c][i]);
else
OLED_WR_DATA(F6x8[c][i]);
}
}
}
/**
* @function: void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_tChar_Size, uint8_t Color_Turn)
* @description: 在OLED12864特定位置开始显示字符串
* @param {uint8_t} x待显示字符串的开始横坐标x:0~127
* @param {uint8_t} y待显示字符串的开始纵坐标 y:0~7,若选择字体大小为16,则两行数字之间需要间隔2,若选择字体大小为12,间隔1
* @param {uint8_t} *chr待显示的字符串
* @param {uint8_t} Char_Size待显示字符串的字体大小,选择字体 16/12,16为8X16,12为6x8
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowString(uint8_t x,uint8_t y,char*chr,uint8_t Char_Size, uint8_t Color_Turn)
{
uint8_t j=0;
while (chr[j]!='\0')
{ OLED_ShowChar(x,y,chr[j],Char_Size, Color_Turn);
if (Char_Size == 12) //6X8的字体列加6,显示下一个字符
x += 6;
else //8X16的字体列加8,显示下一个字符
x += 8;
if (x > 122 && Char_Size==12) //TextSize6x8如果一行不够显示了,从下一行继续显示
{
x = 0;
y++;
}
if (x > 120 && Char_Size== 16) //TextSize8x16如果一行不够显示了,从下一行继续显示
{
x = 0;
y++;
}
j++;
}
}
/**
* @function: void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2, Color_Turn)
* @description: 显示数字
* @param {uint8_t} x待显示的数字起始横坐标,x:0~126
* @param {uint8_t} y待显示的数字起始纵坐标, y:0~7,若选择字体大小为16,则两行数字之间需要间隔2,若选择字体大小为12,间隔1
* @param {unsigned int} num:输入的数据
* @param {uint8_t } len:输入的数据位数
* @param {uint8_t} size2:输入的数据大小,选择 16/12,16为8X16,12为6x8
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2, uint8_t Color_Turn)
{
uint8_t t,temp;
uint8_t enshow=0;
for(t=0;t<len;t++)
{
temp=(num/oled_pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ',size2, Color_Turn);
continue;
}else enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2, Color_Turn);
}
}
/**
* @function: void OLED_Showdecimal(uint8_t x,uint8_t y,float num,uint8_t z_len,uint8_t f_len,uint8_t size2, uint8_t Color_Turn)
* @description: 显示正负浮点数
* @param {uint8_t} x待显示的数字起始横坐标,x:0~126
* @param {uint8_t} y待显示的数字起始纵坐标, y:0~7,若选择字体大小为16,则两行数字之间需要间隔2,若选择字体大小为12,间隔1
* @param {float} num:输入的浮点型数据
* @param {uint8_t } z_ len:整数部分的位数
* @param {uint8_t } f_len: 小数部分的位数
* @param {uint8_t} size2:输入的数据大小,选择 16/12,16为8X16,12为6x8
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_Showdecimal(uint8_t x,uint8_t y,float num,uint8_t z_len,uint8_t f_len,uint8_t size2, uint8_t Color_Turn)
{
uint8_t t,temp,i=0;//i为负数标志位
uint8_t enshow;
int z_temp,f_temp;
if(num<0)
{
z_len+=1;
i=1;
num=-num;
}
z_temp=(int)num;
//整数部分
for(t=0;t<z_len;t++)
{
temp=(z_temp/oled_pow(10,z_len-t-1))%10;
if(enshow==0 && t<(z_len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ',size2, Color_Turn);
continue;
}
else
enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2, Color_Turn);
}
//小数点
OLED_ShowChar(x+(size2/2)*(z_len),y,'.',size2, Color_Turn);
f_temp=(int)((num-z_temp)*(oled_pow(10,f_len)));
//小数部分
for(t=0;t<f_len;t++)
{
temp=(f_temp/oled_pow(10,f_len-t-1))%10;
OLED_ShowChar(x+(size2/2)*(t+z_len)+5,y,temp+'0',size2, Color_Turn);
}
if(i==1)//如果为负,就将最前的一位赋值‘-’
{
OLED_ShowChar(x,y,'-',size2, Color_Turn);
i=0;
}
}
/**
* @function: void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no, uint8_t Color_Turn)
* @description: 在OLED特定位置开始显示16X16汉字
* @param {uint8_t} x待显示的汉字起始横坐标x: 0~112,两列汉字之间需要间隔16
* @param {uint8_t} y待显示的汉字起始纵坐标 y: 0~6 , 两行汉字之间需要间隔2
* @param {uint8_t} no待显示的汉字编号
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no, uint8_t Color_Turn)
{
uint8_t t=0;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
if (Color_Turn)
OLED_WR_DATA(~Hzk[2*no][t]); //显示汉字的上半部分
else
OLED_WR_DATA(Hzk[2*no][t]); //显示汉字的上半部分
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
if (Color_Turn)
OLED_WR_DATA(~Hzk[2*no+1][t]); //显示汉字的上半部分
else
OLED_WR_DATA(Hzk[2*no+1][t]);//显示汉字的上半部分
}
}
/**
* @function: void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn)
* @description: 在OLED特定区域显示BMP图片
* @param {uint8_t} x0图像开始显示横坐标 x0:0~127
* @param {uint8_t} y0图像开始显示纵坐标 y0:0~7
* @param {uint8_t} x1图像结束显示横坐标 x1:1~128
* @param {uint8_t} y1图像结束显示纵坐标 y1:1~8
* @param {uint8_t} *BMP待显示的图像数据
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn)
{
uint32_t j = 0;
uint8_t x = 0, y = 0;
if(y1%8==0)
y = y1/8;
else
y = y1/8 + 1;
for(y=y0;y<y1;y++)
{
OLED_Set_Pos(x0,y);
for(x=x0;x<x1;x++)
{
if (Color_Turn)
OLED_WR_DATA(~BMP[j++]);//显示反相图片
else
OLED_WR_DATA(BMP[j++]);//显示图片
}
}
}
/**
* @function: void OLED_HorizontalShift(uint8_t direction)
* @description: 屏幕内容水平全屏滚动播放
* @param {uint8_t} direction LEFT 0x27 RIGHT 0x26
* @return {*}
*/
void OLED_HorizontalShift(uint8_t direction)
{
OLED_WR_CMD(0x2e);//停止滚动
OLED_WR_CMD(direction);//设置滚动方向
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0x00);//设置开始页地址
OLED_WR_CMD(0x07);//设置每个滚动步骤之间的时间间隔的帧频
// 0x00-5帧, 0x01-64帧, 0x02-128帧, 0x03-256帧, 0x04-3帧, 0x05-4帧, 0x06-25帧, 0x07-2帧,
OLED_WR_CMD(0x07);//设置结束页地址
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0xff);//虚拟字节设置,默认为0xff
OLED_WR_CMD(0x2f);//开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
}
/**
* @function: void OLED_Some_HorizontalShift(uint8_t direction,uint8_t start,uint8_t end)
* @description: 屏幕部分内容水平滚动播放
* @param {uint8_t} direction LEFT 0x27 RIGHT 0x26
* @param {uint8_t} start 开始页地址 0x00~0x07
* @param {uint8_t} end 结束页地址 0x01~0x07
* @return {*}
*/
void OLED_Some_HorizontalShift(uint8_t direction,uint8_t start,uint8_t end)
{
OLED_WR_CMD(0x2e);//停止滚动
OLED_WR_CMD(direction);//设置滚动方向
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(start);//设置开始页地址
OLED_WR_CMD(0x07);//设置每个滚动步骤之间的时间间隔的帧频,0x07即滚动速度2帧
OLED_WR_CMD(end);//设置结束页地址
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0xff);//虚拟字节设置,默认为0xff
OLED_WR_CMD(0x2f);//开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
}
/**
* @function: void OLED_VerticalAndHorizontalShift(uint8_t direction)
* @description: 屏幕内容垂直水平全屏滚动播放
* @param {uint8_t} direction 右上滚动 0x29
* 左上滚动 0x2A
* @return {*}
*/
void OLED_VerticalAndHorizontalShift(uint8_t direction)
{
OLED_WR_CMD(0x2e);//停止滚动
OLED_WR_CMD(direction);//设置滚动方向
OLED_WR_CMD(0x01);//虚拟字节设置
OLED_WR_CMD(0x00);//设置开始页地址
OLED_WR_CMD(0x07);//设置每个滚动步骤之间的时间间隔的帧频,即滚动速度
OLED_WR_CMD(0x07);//设置结束页地址
OLED_WR_CMD(0x01);//垂直滚动偏移量
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0xff);//虚拟字节设置,默认为0xff
OLED_WR_CMD(0x2f);//开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
}
/**
* @function: void OLED_DisplayMode(uint8_t mode)
* @description: 屏幕内容取反显示
* @param {uint8_t} direction ON 0xA7 ,
* OFF 0xA6 默认此模式,设置像素点亮
* @return {*}
*/
void OLED_DisplayMode(uint8_t mode)
{
OLED_WR_CMD(mode);
}
/**
* @function: void OLED_IntensityControl(uint8_t intensity)
* @description: 屏幕亮度调节
* @param {uint8_t} intensity 0x00~0xFF,RESET=0x7F
* @return {*}
*/
void OLED_IntensityControl(uint8_t intensity)
{
OLED_WR_CMD(0x81);
OLED_WR_CMD(intensity);
}
/*
* oledfont.c
*
* Created on: Jul 24, 2022
* Author: Unicorn_Li
*/
//#include "oledfont.h"
//8*6 ASCII字符集点阵
const unsigned char F6x8[][6] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp
0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// !
0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// "
0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// #
0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $
0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// %
0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// &
0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// '
0x00, 0x00, 0x1c, 0x22, 0x41, 0x00,// (
0x00, 0x00, 0x41, 0x22, 0x1c, 0x00,// )
0x00, 0x14, 0x08, 0x3E, 0x08, 0x14,// *
0x00, 0x08, 0x08, 0x3E, 0x08, 0x08,// +
0x00, 0x00, 0x00, 0xA0, 0x60, 0x00,// ,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08,// -
0x00, 0x00, 0x60, 0x60, 0x00, 0x00,// .
0x00, 0x20, 0x10, 0x08, 0x04, 0x02,// /
0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1
0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2
0x00, 0x21, 0x41, 0x45, 0x4B, 0x31,// 3
0x00, 0x18, 0x14, 0x12, 0x7F, 0x10,// 4
0x00, 0x27, 0x45, 0x45, 0x45, 0x39,// 5
0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
0x00, 0x01, 0x71, 0x09, 0x05, 0x03,// 7
0x00, 0x36, 0x49, 0x49, 0x49, 0x36,// 8
0x00, 0x06, 0x49, 0x49, 0x29, 0x1E,// 9
0x00, 0x00, 0x36, 0x36, 0x00, 0x00,// :
0x00, 0x00, 0x56, 0x36, 0x00, 0x00,// ;
0x00, 0x08, 0x14, 0x22, 0x41, 0x00,// <
0x00, 0x14, 0x14, 0x14, 0x14, 0x14,// =
0x00, 0x00, 0x41, 0x22, 0x14, 0x08,// >
0x00, 0x02, 0x01, 0x51, 0x09, 0x06,// ?
0x00, 0x32, 0x49, 0x59, 0x51, 0x3E,// @
0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,// A
0x00, 0x7F, 0x49, 0x49, 0x49, 0x36,// B
0x00, 0x3E, 0x41, 0x41, 0x41, 0x22,// C
0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C,// D
0x00, 0x7F, 0x49, 0x49, 0x49, 0x41,// E
0x00, 0x7F, 0x09, 0x09, 0x09, 0x01,// F
0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A,// G
0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F,// H
0x00, 0x00, 0x41, 0x7F, 0x41, 0x00,// I
0x00, 0x20, 0x40, 0x41, 0x3F, 0x01,// J
0x00, 0x7F, 0x08, 0x14, 0x22, 0x41,// K
0x00, 0x7F, 0x40, 0x40, 0x40, 0x40,// L
0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F,// M
0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F,// N
0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E,// O
0x00, 0x7F, 0x09, 0x09, 0x09, 0x06,// P
0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
0x00, 0x7F, 0x09, 0x19, 0x29, 0x46,// R
0x00, 0x46, 0x49, 0x49, 0x49, 0x31,// S
0x00, 0x01, 0x01, 0x7F, 0x01, 0x01,// T
0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F,// U
0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F,// V
0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F,// W
0x00, 0x63, 0x14, 0x08, 0x14, 0x63,// X
0x00, 0x07, 0x08, 0x70, 0x08, 0x07,// Y
0x00, 0x61, 0x51, 0x49, 0x45, 0x43,// Z
0x00, 0x00, 0x7F, 0x41, 0x41, 0x00,// [
0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55,// 55
0x00, 0x00, 0x41, 0x41, 0x7F, 0x00,// ]
0x00, 0x04, 0x02, 0x01, 0x02, 0x04,// ^
0x00, 0x40, 0x40, 0x40, 0x40, 0x40,// _
0x00, 0x00, 0x01, 0x02, 0x04, 0x00,// '
0x00, 0x20, 0x54, 0x54, 0x54, 0x78,// a
0x00, 0x7F, 0x48, 0x44, 0x44, 0x38,// b
0x00, 0x38, 0x44, 0x44, 0x44, 0x20,// c
0x00, 0x38, 0x44, 0x44, 0x48, 0x7F,// d
0x00, 0x38, 0x54, 0x54, 0x54, 0x18,// e
0x00, 0x08, 0x7E, 0x09, 0x01, 0x02,// f
0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,// g
0x00, 0x7F, 0x08, 0x04, 0x04, 0x78,// h
0x00, 0x00, 0x44, 0x7D, 0x40, 0x00,// i
0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,// j
0x00, 0x7F, 0x10, 0x28, 0x44, 0x00,// k
0x00, 0x00, 0x41, 0x7F, 0x40, 0x00,// l
0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,// m
0x00, 0x7C, 0x08, 0x04, 0x04, 0x78,// n
0x00, 0x38, 0x44, 0x44, 0x44, 0x38,// o
0x00, 0xFC, 0x24, 0x24, 0x24, 0x18,// p
0x00, 0x18, 0x24, 0x24, 0x18, 0xFC,// q
0x00, 0x7C, 0x08, 0x04, 0x04, 0x08,// r
0x00, 0x48, 0x54, 0x54, 0x54, 0x20,// s
0x00, 0x04, 0x3F, 0x44, 0x40, 0x20,// t
0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C,// u
0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C,// v
0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C,// w
0x00, 0x44, 0x28, 0x10, 0x28, 0x44,// x
0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,// y
0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z
0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// horiz lines
};
//16*8 ASCII字符集点阵
const unsigned char F8X16[]=
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//sp /0
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! /1
0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" /2
0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# /3
0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ /4
0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% /5
0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& /6
0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' /7
0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( /8
0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) /9
0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* /10
0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ /11
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, /12
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- /13
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. /14
0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// /15
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 /16
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 /17
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 /18
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 /19
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 /20
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 /21
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 /22
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 /23
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 /24
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 /25
0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: /26
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; /27
0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< /28
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= /29
0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> /30
0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? /31
0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ /32
0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A /33
0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B /34
0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C /35
0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D /36
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E /37
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F /38
0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G /39
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H /40
0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I /41
0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J /42
0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K /43
0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L /44
0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M /45
0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N /46
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O /47
0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P /48
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q /49
0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R /50
0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S /51
0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T /52
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U /53
0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V /54
0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W /55
0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X /56
0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y /57
0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z /58
0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ /59
0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ /60
0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] /61
0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ /62
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ /63
0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` /64
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a /65
0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b /66
0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c /67
0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d /68
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e /69
0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f /70
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g /71
0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h /72
0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i /73
0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j /74
0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k /75
0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l /76
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m /77
0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n /78
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o /79
0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p /80
0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q /81
0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r /82
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s /83
0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t /84
0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u /85
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v /86
0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w /87
0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x /88
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y /89
0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z /90
0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ /91
0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} /92
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00};//| /93
//部分汉字 阴码,列行式,逆向
const unsigned char Hzk[][32]=
{
{0x40,0x22,0x14,0x08,0xF4,0x02,0x00,0xF8,0x08,0x08,0xFF,0x08,0x08,0xF8,0x00,0x00},
{0x08,0x44,0x82,0x41,0x3F,0x00,0x20,0x63,0x21,0x21,0x3F,0x21,0x29,0x33,0x60,0x00},/*"独",0*/
{0x20,0x10,0xE8,0x24,0x27,0x24,0x24,0xE4,0x24,0x34,0x2C,0x20,0xE0,0x00,0x00,0x00},
{0x80,0x60,0x1F,0x09,0x09,0x09,0x09,0x7F,0x09,0x09,0x49,0x89,0x7F,0x00,0x00,0x00},/*"角",1*/
{0x00,0x00,0x7C,0x54,0x55,0x56,0x54,0x7C,0x54,0x56,0x55,0x54,0x7C,0x00,0x00,0x00},
{0x01,0x01,0x01,0xFD,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0xFD,0x01,0x01,0x01,0x00},/*"兽",2*/
};
//128*64图片
unsigned char BMP1[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x40,0xE0,0xE0,0x60,
0x00,0x40,0x80,0x00,0x00,0x00,0x80,0x80,0x60,0x60,0x10,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x90,0xB2,0x66,0x6E,0xEC,0xC9,0x83,0x02,0x00,0x40,0x80,
0x00,0x0C,0x0C,0x01,0x03,0x07,0x0F,0x11,0x20,0x40,0x80,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x08,0x18,0x3B,0x37,0x66,0xEE,0xEE,0xCC,0x88,0x80,0x00,0x00,
0x01,0x02,0x04,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x0F,0x00,0x00,0x00,0x00,0x00,
0x00,0x3E,0x40,0x40,0x40,0x3E,0x00,0x7E,0x04,0x08,0x10,0x7E,0x00,0x7E,0x00,0x3C,
0x42,0x42,0x42,0x42,0x00,0x7E,0x42,0x42,0x42,0x7E,0x00,0x7E,0x04,0x08,0x10,0x7E,/*"C:\Users\HP\Desktop\UNICORN.BMP",0*/
};
oled.h
#ifndef OLED_OLED_H_
#define OLED_OLED_H_
#include "stm32f1xx_hal.h"
//#include "oledfont.h"
extern I2C_HandleTypeDef hi2c1;
void OLED_WR_CMD(uint8_t cmd);
void OLED_WR_DATA(uint8_t data);
void OLED_Init(void);
void OLED_Clear(void);
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Set_Pos(uint8_t x, uint8_t y);
void OLED_On(void);
void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2,uint8_t Color_Turn);
void OLED_Showdecimal(uint8_t x,uint8_t y,float num,uint8_t z_len,uint8_t f_len,uint8_t size2, uint8_t Color_Turn);
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size,uint8_t Color_Turn);
void OLED_ShowString(uint8_t x,uint8_t y,char*chr,uint8_t Char_Size,uint8_t Color_Turn);
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no,uint8_t Color_Turn);
void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn);
void OLED_HorizontalShift(uint8_t direction);
void OLED_Some_HorizontalShift(uint8_t direction,uint8_t start,uint8_t end);
void OLED_VerticalAndHorizontalShift(uint8_t direction);
void OLED_DisplayMode(uint8_t mode);
void OLED_IntensityControl(uint8_t intensity);
extern const unsigned char F6x8[][6];
extern const unsigned char F8X16[];
extern const unsigned char Hzk[][32];
extern unsigned char BMP1[];
#endif /* OLED_OLED_H_ */
6.openmv
参考链接: link
import sensor, image, time,math,pyb
from pyb import UART,LED
import json
import ustruct
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(False) # must be turned off for color tracking
red_threshold_01=(0, 89, 125, 13, -34, 84)
clock = time.clock()
uart = UART(3,115200) #定义串口3变量
uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters
def find_max(blobs): #定义寻找色块面积最大的函数
max_size=0
for blob in blobs:
if blob.pixels() > max_size:
max_blob=blob
max_size = blob.pixels()
return max_blob
def sending_data(cx,cy,cw,ch):
global uart;
#frame=[0x2C,18,cx%0xff,int(cx/0xff),cy%0xff,int(cy/0xff),0x5B];
#data = bytearray(frame)
data = ustruct.pack("<bbhhhhb", #格式为俩个字符俩个短整型(2字节)
0x2C, #帧头1
0x12, #帧头2
int(cx), # up sample by 4 #数据1
int(cy), # up sample by 4 #数据2
int(cw), # up sample by 4 #数据1
int(ch), # up sample by 4 #数据2
0x5B)
uart.write(data); #必须要传入一个字节数组
while(True):
clock.tick()
img = sensor.snapshot()
blobs = img.find_blobs([red_threshold_01])
cx=0;cy=0;
if blobs:
max_b = find_max(blobs)
#如果找到了目标颜色
cx=max_b[5]
cy=max_b[6]
cw=max_b[2]
ch=max_b[3]
img.draw_rectangle(max_b[0:4]) # rect
img.draw_cross(max_b[5], max_b[6]) # cx, cy
#sending_data(cx,cy,cw,ch)
else:
cx=0
cy=0
cw=0
ch=0
FH = bytearray([0x2C,0x12,cx,cy,cw,ch,0x5B])
uart.write(FH)
print(cx,cy,cw,ch)
7.main函数代码
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_TIM4_Init();
MX_TIM5_Init();
MX_TIM6_Init();
MX_TIM8_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1,(uint8_t *)&USART1_Data,1); //开启串口1的接收中断
HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL); //开启编码器模式
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_Base_Start(&htim2);
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL); //开启编码器模式
HAL_TIM_Base_Start_IT(&htim3);
HAL_TIM_Base_Start(&htim3);
HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL); //开启编码器模式
HAL_TIM_Base_Start_IT(&htim4);
HAL_TIM_Base_Start(&htim4);
HAL_TIM_Encoder_Start(&htim5, TIM_CHANNEL_ALL); //开启编码器模式
HAL_TIM_Base_Start_IT(&htim5);
HAL_TIM_Base_Start(&htim5);
HAL_TIM_Base_Start_IT(&htim6); //开启定时器的中断
HAL_TIM_Base_Start(&htim6);
HAL_TIM_Base_Start_IT(&htim8);
HAL_TIM_Base_Start(&htim8);
HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_4);
OLED_Init(); //OLED初始
OLED_Clear(); //清屏
OLED_ShowString(0,0,"uart",16,0);//正相显示8X16字符串
OLED_ShowString(1,3,"cx",16,0);//正相显示8X16字符串
OLED_ShowString(32,3,"cy",16,0);//正相显示8X16字符串
OLED_ShowString(64,3,"cw",16,0);//正相显示8X16字符串
OLED_ShowString(96,3,"ch",16,0);//正相显示8X16字符串
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// if(a<0)
// a=-a;
// OLED_ShowNum(0,0,a,4,16, 0);//正相显示5位8X16数字“6”
if(USART1_RX_ST&0x8000)
{
if(USART1_RX_BUFF[0]==0x2c&& USART1_RX_BUFF[1]==0x12)
{
cx=USART1_RX_BUFF[2];
cy=USART1_RX_BUFF[3];
cw=USART1_RX_BUFF[4];
ch=USART1_RX_BUFF[5];
}
OLED_ShowNum(0,6,cx,4,16, 0);//正相显示5位8X16数字“6”
OLED_ShowNum(32,6,cy,4,16, 0);//正相显示5位8X16数字“6”
OLED_ShowNum(64,6,cw,4,16, 0);//正相显示5位8X16数字“6”
OLED_ShowNum(96,6,ch,4,16, 0);//正相显示5位8X16数字“6”
USART1_RX_ST=0;//标志位清0,准备下次接收
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
8.最后效果(pid还有运动方程的参数不同效果不同)
颜色追踪小车