手上有個C8t6和超聲波模塊,那就用c8t6做個測距+oled顯示吧,不過這次使用寄存器開發(fā),查詢文檔查了半天,基礎(chǔ)不是很扎實,共勉!
代碼部分
為了便于讀取和修改代碼oled初始化存于oled.c中,超聲波初始化存于HC_SR04.c中
OLED部分
以下代碼可以直接使用,注意一下改變頭文件中oled接口和字模庫就行,難度不大!
先在頭文件中定義oled連接的端口方便在程序中解讀,同時聲明需要用到的函數(shù),方便尋找函數(shù)!
以下為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 //寫數(shù)據(jù)
//OLED控制用函數(shù)
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
頭文件定義后,在模塊文件中寫頭文件中定義的函數(shù)主體部分
以下為主體部分!
#include 'oled.h'
#include 'stdlib.h'
#include 'oledfont.h' //存放字模的文件
#include 'delay.h' // 延時函數(shù)
u8 OLED_GRAM[128][8]; //oled的緩存區(qū),用來儲存需要寫入的字模
void OLED_Refresh_Gram(void) //重裝字模,每一次改變SRAM后都要重裝導(dǎo)入到Gram里面
{
u8 i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte (0xb0+i,OLED_CMD); //設(shè)置頁地址(0~7)
OLED_WR_Byte (0x00,OLED_CMD); //設(shè)置顯示位置—列低地址
OLED_WR_Byte (0x10,OLED_CMD); //設(shè)置顯示位置—列高地址
for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
}
}
//向OLED寫入一個字節(jié)。
//dat:要寫入的數(shù)據(jù)/命令
//cmd:數(shù)據(jù)/命令標志 0,表示命令;1,表示數(shù)據(jù);
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
}
//關(guān)閉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
}
//清屏函數(shù),清完屏,整個屏幕是黑色的!和沒點亮一樣!!!
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();//更新顯示
}
//畫點 ,即將字模的對應(yīng)點點亮
//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]; //調(diào)用1206字體 else temp=oled_asc2_1608[chr][t]; //調(diào)用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個數(shù)字 //x,y :起點坐標 //len :數(shù)字的位數(shù) //size:字體大小 //mode:模式 0,填充模式;1,疊加模式 //num:數(shù)值(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); } } //顯示字符串,原理其實就是調(diào)用多個字符寫入 //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!='