基于STM32C8T6的超声波和Oled开发(寄存器版)
2024-08-26 来源:cnblogs
手上有个C8t6和超声波模块,那就用c8t6做个测距+oled显示吧,不过这次使用寄存器开发,查询文档查了半天,基础不是很扎实,共勉!
代码部分
为了便于读取和修改代码oled初始化存于oled.c中,超声波初始化存于HC_SR04.c中
OLED部分
以下代码可以直接使用,注意一下改变头文件中oled接口和字模库就行,难度不大!
先在头文件中定义oled连接的端口方便在程序中解读,同时声明需要用到的函数,方便寻找函数!
以下为oled.h头文件部分!
#ifndef __OLED_H
#define __OLED_H
#include 'sys.h'
//-----------------OLED端口定义----------------
#define OLED_RST_Clr() PBout(3)=0 //RST
#define OLED_RST_Set() PBout(3)=1 //RST
#define OLED_RS_Clr() PAout(15)=0 //DC
#define OLED_RS_Set() PAout(15)=1 //DC
#define OLED_SCLK_Clr() PBout(5)=0 //SCL
#define OLED_SCLK_Set() PBout(5)=1 //SCL
#define OLED_SDIN_Clr() PBout(4)=0 //SDA
#define OLED_SDIN_Set() PBout(4)=1 //SDA
#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据
//OLED控制用函数
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);
#endif
头文件定义后,在模块文件中写头文件中定义的函数主体部分
以下为主体部分!
#include 'oled.h'
#include 'stdlib.h'
#include 'oledfont.h' //存放字模的文件
#include 'delay.h' // 延时函数
u8 OLED_GRAM[128][8]; //oled的缓存区,用来储存需要写入的字模
void OLED_Refresh_Gram(void) //重装字模,每一次改变SRAM后都要重装导入到Gram里面
{
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][i],OLED_DATA);
}
}
//向OLED写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
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();
}
//开启OLED显示
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
}
//关闭OLED显示
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][i]=0X00;
OLED_Refresh_Gram();//更新显示
}
//画点 ,即将字模的对应点点亮
//x:0~127
//y:0~63
//t:1 填充 0,清空
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;
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示
//size:选择字体 16/12
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)temp=oled_asc2_1206[chr][t]; //调用1206字体 else temp=oled_asc2_1608[chr][t]; //调用1608字体 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; } } } } //显示2个数字 //x,y :起点坐标 //len :数字的位数 //size:字体大小 //mode:模式 0,填充模式;1,叠加模式 //num:数值(0~4294967295); 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); } } //显示字符串,原理其实就是调用多个字符写入 //x,y:起点坐标 //*p:字符串起始地址 //用16字体 void OLED_ShowString(u8 x,u8 y,const u8 *p) { #define MAX_CHAR_POSX 122 #define MAX_CHAR_POSY 58 while(*p!='