設(shè)計(jì)背景
我組大部分成員皆是初次接觸嵌入式開發(fā)系統(tǒng),因此根據(jù)本次夏令營(yíng)學(xué)習(xí)及導(dǎo)師推薦下我們選擇了設(shè)計(jì)難度較低的OLED時(shí)鐘設(shè)計(jì)。在導(dǎo)師的幫助下完成了整個(gè)工程的搭建。
設(shè)計(jì)思路
采用市面上比較常見的SSD1306顯示屏作為時(shí)鐘的載體。設(shè)計(jì)的思路是:
1.使用本次夏令營(yíng)下發(fā)的Psoc6-evaluationkit-062S2開發(fā)板驅(qū)動(dòng)OLED屏
2.使用RT-THREAD Studio設(shè)置RTC獲取時(shí)間
3.將時(shí)間顯示在OLED屏上并設(shè)計(jì)簡(jiǎn)單的數(shù)字滾動(dòng)功能
開發(fā)工具
1.Psoc6-evaluationkit-062S2開發(fā)板
2.RT-THREAD Studio
3.SSD1306四排真OLED屏
RT-THREAD Studio軟件包設(shè)置
其中參考了SSD1306軟件包及RTC例程因此SSD1306軟件包需單獨(dú)下載
開發(fā)心得
作為初次接觸嵌入式操作系統(tǒng)的初學(xué)者,學(xué)習(xí)中有些許困難。主要在于不能清楚的掌握模塊的調(diào)用,初次接觸線程的概念、使用經(jīng)過rtt封裝過的C語言頭文件及rtt中的基本函數(shù)。在大致讀懂后明白了rtt已經(jīng)將許多模塊寫好可以直接調(diào)用,各位前輩的軟件包是的開發(fā)更具模塊化。裸機(jī)開發(fā)與嵌入式操作系統(tǒng)開發(fā)的區(qū)別很大但EOS的簡(jiǎn)潔明了顯而易見,不過代碼的移植也是入門的難點(diǎn)之一。
下附完整的工程代碼
工程代碼
1.OLED屏驅(qū)動(dòng)
#include "oled.h"
#include
#include
#include "codetab.h"
//oled顯示尺寸
uint16_t const displayWidth = 128;
uint16_t const displayHeight = 64;
/* OLED顯存
[0]0 1 2 3 ... 127
[1]0 1 2 3 ... 127
[2]0 1 2 3 ... 127
[3]0 1 2 3 ... 127
[4]0 1 2 3 ... 127
[5]0 1 2 3 ... 127
[6]0 1 2 3 ... 127
[7]0 1 2 3 ... 127 /
static uint8_t OLED_RAM[8][128];//定義GDDRAM緩存區(qū)
#define CW_OLED_I2C CW_I2C1
#define OLED_ADDR 0x3c
#define SSD1306_CTRL_CMD 0x00
#define SSD1306_CTRL_DATA 0x40
#define SSD1306_MASK_CONT (0x1<<7)
static struct rt_i2c_bus_device i2c_bus;
void OLED_I2C_Init(void)
{
i2c_bus = (struct rt_i2c_bus_device )rt_device_find(PKG_USING_SSD1306_I2C_BUS_NAME);
if (i2c_bus == RT_NULL)
{
rt_kprintf("can not find %s device", PKG_USING_SSD1306_I2C_BUS_NAME);
return;
}
}
//向OLED寄存器地址寫一個(gè)byte的數(shù)據(jù)
//int I2C_WriteByte(uint8_t addr,uint8_t data)
//{
//
// return 0;
//}
/ ***********************************************************
Prototype : void WriteCmd(uint8_t IIC_Command)
Parameters : IIC_Command
return : none
Description : 寫命令
/
void WriteCmd(uint8_t IIC_Command)
{
// I2C_WriteByte(0x00, IIC_Command);
uint8_t buf[2] = {SSD1306_CTRL_CMD, IIC_Command};
rt_i2c_master_send(i2c_bus, OLED_ADDR, RT_I2C_WR, buf, 2);
}
/
Prototype : void WriteDat(uint8_t IIC_Data)
Parameters : IIC_Data
return : none
Description : 寫數(shù)據(jù)
/
void WriteDat(uint8_t IIC_Data)
{
//I2C_WriteByte(0x40, IIC_Data);
uint8_t buf[2] = {SSD1306_CTRL_DATA, IIC_Data};
rt_i2c_master_send(i2c_bus, OLED_ADDR, RT_I2C_WR, buf, 2);
}
/
Prototype : void OLED_Init(void)
Parameters : none
return : none
Description : 初始化OLED模塊
/
void OLED_Init(void)
{
OLED_I2C_Init();
rt_thread_mdelay(500);
WriteCmd(0xAE); //開顯示
WriteCmd(0x20); //設(shè)置內(nèi)存尋址模式
WriteCmd(0x00); //00,水平尋址模式;01,垂直尋址模式;10,頁面尋址模式(重置);11,無效
WriteCmd(0x21); //設(shè)置列開始和結(jié)束地址
WriteCmd(0x00); //列起始地址,范圍:0 – 127d (默認(rèn)值 = 0d)
WriteCmd(0x7F); //列結(jié)束地址,范圍:0 – 127d (默認(rèn)值 = 127d)
WriteCmd(0x22); //頁面設(shè)置開始和結(jié)束地址
WriteCmd(0x00); //頁面起始地址,范圍:0-7d (默認(rèn)值= 0d)
WriteCmd(0x07); //頁面結(jié)束地址,范圍:0-7d (默認(rèn)值= 7d)
WriteCmd(0xc8); //設(shè)置COM輸出掃描方向
WriteCmd(0x40); //--設(shè)置起始行地址
WriteCmd(0x81); //--set contrast control register
WriteCmd(0xff); //亮度調(diào)節(jié) 0x00~0xff
WriteCmd(0xa1); //--設(shè)置段重新映射0到127
WriteCmd(0xa6); //--設(shè)置正常顯示
WriteCmd(0xa8); //--設(shè)置復(fù)用比(1 ~ 64)
WriteCmd(0x3F); //
WriteCmd(0xa4); //0xa4,輸出遵循RAM內(nèi)容;0xa5,Output忽略RAM內(nèi)容
WriteCmd(0xd3); //-設(shè)置顯示抵消
WriteCmd(0x00); //-not offset
WriteCmd(0xd5); //--設(shè)置顯示時(shí)鐘分頻/振蕩器頻率
WriteCmd(0xf0); //--設(shè)置分率
WriteCmd(0xd9); //--設(shè)置pre-charge時(shí)期
WriteCmd(0x22); //
WriteCmd(0xda); //--設(shè)置com大頭針硬件配置
WriteCmd(0x12);
WriteCmd(0xdb); //--設(shè)置vcomh
WriteCmd(0x20); //0x20,0.77xVcc
WriteCmd(0x8d); //--設(shè)置DC-DC
WriteCmd(0x14); //
WriteCmd(0xaf); //--打開oled面板
OLED_FullyClear();//清屏
}
/
Prototype : void OLED_ON(void)
Parameters : none
return : none
Description : 將OLED從休眠中喚醒
/
void OLED_ON(void)
{
WriteCmd(0X8D); //設(shè)置電荷泵
WriteCmd(0X14); //開啟電荷泵
WriteCmd(0XAF); //OLED喚醒
}
/
Prototype : void OLED_OFF(void)
Parameters : none
return : none
Description : 讓OLED休眠 -- 休眠模式下,OLED功耗不到10uA
/
void OLED_OFF(void)
{
WriteCmd(0X8D); //設(shè)置電荷泵
WriteCmd(0X10); //關(guān)閉電荷泵
WriteCmd(0XAE); //OLED休眠
}
/
Prototype : void OLED_RefreshRAM(void)
Parameters : none
return : none
Description : 全屏填充
/
void OLED_RefreshRAM(void)
{
for(uint16_t m = 0; m < displayHeight/8; m++)
{
for(uint16_t n = 0; n < displayWidth; n++)
{
WriteDat(OLED_RAM[m][n]);
}
}
}
/
Prototype : void OLED_RefreshRAM_Test(void)
Parameters : Page_Start 頁開始地址(最小為0)
Parameters : Page_Stop 頁結(jié)束地址(最大為7)
Parameters : Column_Start 列開始地址(最小為0)
Parameters : Column_Stop 列結(jié)束地址(最大為127)
return : none
Description : 區(qū)域填充
/
void OLED_RefreshPartRAM(uint8_t Page_Start, uint8_t Page_Stop, uint8_t Column_Start, uint8_t Column_Stop)
{
WriteCmd(0X21); //設(shè)置列地址
WriteCmd(Column_Start); //列開始地址
WriteCmd(Column_Stop); //列結(jié)束地址
WriteCmd(0X22); //設(shè)置頁地址
WriteCmd(Page_Start); //頁開始地址
WriteCmd(Page_Stop); //頁結(jié)束地址
for(uint16_t m = Page_Start; m < (Page_Stop + 1); m++)
{
for(uint16_t n = Column_Start; n < (Column_Stop + 1); n++)
{
WriteDat(OLED_RAM[m][n]);
}
}
}
/
Prototype : void OLED_ClearRAM(void)
Parameters : none
return : none
Description : 清除數(shù)據(jù)緩沖區(qū)
/
void OLED_ClearRAM(void)
{
for(uint16_t m = 0; m < displayHeight/8; m++)
{
for(uint16_t n = 0; n < displayWidth; n++)
{
OLED_RAM[m][n] = 0x00;
}
}
}
/
Prototype : void OLED_Fill(uint8_t fill_Data)
Parameters : fill_Data 填充的1字節(jié)數(shù)據(jù)
return : none
Description : 全屏填充 0x000xff127, y:0
*/
void OLED_FullyFill(uint8_t fill_Data)
{
for(uint16_t m = 0; m < displayHeight/8; m++)
{
for(uint16_t n = 0; n < displayWidth; n++)
{
OLED_RAM[m][n] = fill_Data;
}
}
OLED_RefreshRAM();
}
/
Prototype : void OLED_FullyClear(void)
Parameters : none
return : none
Description : 全屏清除
*/
void OLED_FullyClear(void)
{
OLED_FullyFill(RESET_PIXEL);
}
/
Prototype : void OLED_SetPixel(int16_t x, int16_t y, uint8_t set_pixel)
Parameters : x,y -- 起始點(diǎn)坐標(biāo)(x:063);127, y:0
set_pixel 該點(diǎn)的數(shù)據(jù) SET_PIXEL = 1, RESET_PIXEL = 0
return : none
Description : 設(shè)置坐標(biāo)像素點(diǎn)數(shù)據(jù)
*/
void OLED_SetPixel(int16_t x, int16_t y, uint8_t set_pixel)
{
if (x >= 0 && x < displayWidth && y >= 0 && y < displayHeight) {
if(set_pixel){
OLED_RAM[y/8][x] |= (0x01 << (y%8));
}
else{
OLED_RAM[y/8][x] &= ~(0x01 << (y%8));
}
}
}
/
Prototype : void OLED_GetPixel(int16_t x, int16_t y)
Parameters : x,y -- 起始點(diǎn)坐標(biāo)(x:063);127, y:0~63);
return : PixelStatus 像素點(diǎn)狀態(tài) SET_PIXEL = 1, RESET_PIXEL = 0
Description : 獲得坐標(biāo)像素點(diǎn)數(shù)據(jù)
*/
PixelStatus OLED_GetPixel(int16_t x, int16_t y)
{
if(OLED_RAM[y/8][x] >> (y%8) & 0x01)
return SET_PIXEL;
return RESET_PIXEL;
}
/
Prototype : void OLED_ShowStr(int16_t x, int16_t y, uint8_t ch[], uint8_t TextSize)
Parameters : x,y -- 起始點(diǎn)坐標(biāo)(x:0
ch[] -- 要顯示的字符串;
TextSize -- 字符大小(1:68 ; 2:816)
return : none
Description : 顯示codetab.h中的ASCII字符,有68和816可選擇
/
void OLED_ShowStr(int16_t x, int16_t y, uint8_t ch[], uint8_t TextSize)
{
if (x >= 0 && x < displayWidth && y >= 0 && y < displayHeight) {
int32_t c = 0;
uint8_t j = 0;
switch(TextSize)
{
case 1:
{
while(ch[j] != '?')
{
c = ch[j] - 32;
if(c < 0) //無效字符
break;
if(x >= 125 || (127-x < 6))//一行最大顯示字符數(shù):21字節(jié)顯示,多出兩列,不顯示 || 剩余列小于6不能顯示完整字符,換行顯示
{
x = 0;
y += 8;//換行顯示
if(63 - y < 8) // 不足以顯示一行時(shí)不顯示
break;
}
for(uint8_t m = 0; m < 6; m++)
{
for(uint8_t n = 0; n < 8; n++)
{
OLED_SetPixel(x+m, y+n, (F6x8[c][m] >> n) & 0x01);
}
}
x += 6;
j++;
}
}break;
case 2:
{
while(ch[j] != '?')
{
c = ch[j] - 32;
if(c < 0) //無效字符
break;
if(x >= 127 || (127-x < 8))//16字節(jié)顯示 || 剩余列小于8不能顯示完整字符,換行顯示
{
x = 0;
y += 16;//換行顯示
if(63 - y < 16) // 不足以顯示一行時(shí)不顯示
break;
}
for(uint8_t m = 0; m < 2; m++)
{
for(uint8_t n = 0; n < 8; n++)
{
for(uint8_t i = 0; i < 8; i++)
{
OLED_SetPixel(x+n, y+i+m8, (F8X16[c][n+m8] >> i) & 0x01);
}
}
}
x += 8;
j++;
}
}break;
}
}
}
/
Prototype : void OLED_ShowCN(int16_t x, int16_t y, uint8_t ch)
Parameters : x,y -- 起始點(diǎn)坐標(biāo)(x:0127, y:07);
CN[]:漢字在codetab.h中的索引
return : none
Description : 顯示codetab.h中的漢字,1616點(diǎn)陣
/
void OLED_ShowCN(int16_t x, int16_t y, uint8_t ch)
{
if (x >= 0 && x < displayWidth && y >= 0 && y < displayHeight) {
int32_t len = 0;
while(ch[len] != '?')
{
if(x >= 127 || (127-x < 16))//8個(gè)漢字顯示||剩余列小于16不能顯示完整字符,換行顯示
{
x = 0;
y += 16;
if(63 - y < 16) // 不足以顯示一行時(shí)不顯示
break;
}
//需要處理輸入數(shù)據(jù)大于顯示數(shù)據(jù)的問題
for(uint8_t i = 0; i < sizeof(F16x16_CN)/sizeof(GB2312_CN); i++)
{
if(((F16x16_CN[i].index[0] == ch[len]) && (F16x16_CN[i].index[1] == ch[len+1]))){
for(uint8_t m = 0; m < 2; m++) //頁
{
for(uint8_t n = 0; n < 16; n++) // 列
{
for(uint8_t j = 0; j < 8; j++) // 行
{
OLED_SetPixel(x+n, y+j+m8, (F16x16_CN[i].encoder[n+m16] >> j) & 0x01);
}
}
}
x += 16;
len += 2;
break;
}
else if(F16x16_CN[i].index[0] == ch[len] && ch[len] == 0x20){
for(uint8_t m = 0; m < 2; m++)
{
for(uint8_t n = 0; n < 16; n++)
{
for(uint8_t j = 0; j < 8; j++)
{
OLED_SetPixel(x+n, y+j+m8, (F16x16_CN[i].encoder[n+m16] >> j) & 0x01);
}
}
}
x += 16;
len++;
break;
}
}
}
}
}
/ ***
Prototype : void OLED_Show_MixedCH(int16_t x, int16_t y, uint8_t* ch)
Parameters : x,y -- 起始點(diǎn)坐標(biāo)(x:0127, y:07); CN[]:漢字在codetab.h中的索引
return : none
Description : 顯示codetab.h中的漢字,1616點(diǎn)陣,英文,816點(diǎn)陣
/
void OLED_ShowMixedCH(int16_t x, int16_t y, uint8_t ch)
{
if (x >= 0 && x < displayWidth && y >= 0 && y < displayHeight) {
int32_t len = 0, c;
while(ch[len] != '?')
{
if(ch[len] >= 0xa1)//GB2312從0xA1A0開始
{
for(uint8_t i = 0; i < sizeof(F16x16_CN)/sizeof(GB2312_CN); i++)
{
if(((F16x16_CN[i].index[0] == ch[len]) && (F16x16_CN[i].index[1] == ch[len+1])))
{
if(x >= 127|| (127-x < 16))//8個(gè)漢字顯示||剩余列小于16不能顯示完整字符,換行顯示
{
x = 0;
y += 16;
if(63 - y < 16) // 不足以顯示一行時(shí)不顯示
break;
}
for(uint8_t m = 0; m < 2; m++) //頁
{
for(uint8_t n = 0; n < 16; n++) //列
{
for(uint8_t j = 0; j < 8; j++) //行
{
OLED_SetPixel(x+n, y+j+m8, (F16x16_CN[i].encoder[n+m16] >> j) & 0x01);
}
}
}
x += 16;
len += 2;
break;
}
}
}
else if(ch[len] <= 127)//ASCII編碼范圍0-127
{
c = ch[len] - 32;
if(c < 0) // 無效字符
break;
if(x >= 127 || (127-x < 8))//16字節(jié)顯示 || 剩余列小于8不能顯示完整字符,換行顯示
{
x = 0;
y += 16;
if(63 - y < 16) // 不足以顯示一行時(shí)不顯示
break;
}
for(uint8_t m = 0; m < 2; m++)
{
for(uint8_t n = 0; n < 8; n++)
{
for(uint8_t i = 0; i < 8; i++)
{
OLED_SetPixel(x+n, y+i+m8, (F8X16[c][n+m8] >> i) & 0x01);
}
}
}
x += 8;
len++;
}
}
}
}
/ *****
Prototype : void OLED_DrawBMP(int16_t x0,int16_t y0,int16_t L,int16_t H,const uint8_t BMP[])
Parameters : (x0,y0)坐標(biāo)長(zhǎng)L寬H區(qū)域繪制圖像BMP
0<=x0<=127 0<=y0<=63 0<=L+x0<=127 0<=H+y0<= 63 圖像取模 縱向取模,字節(jié)倒序
return : none
Description : 區(qū)域圖像繪制,顯示BMP位圖,格式使用二維數(shù)組存儲(chǔ)
***************************************************************/
void OLED_DrawBMP(int16_t x0,int16_t y0,int16_t L,int16_t H,const uint8_t BMP[])
{
if (x0 >= 0 && x0 < displayWidth && x0+L <= displayWidth &&
y0 >= 0 && y0 < displayHeight && y0+H <= displayHeight) {
uint8_t *p = (uint8_t *)BMP;
for(int16_t y = y0; y < y0+H; y+=8)
{
for(int16_t x = x0; x < x0+L; x++)
{
for(int16_t i = 0; i < 8; i++)
{
// OLED_SetPixel(x, y+i, ((*((uint8_t *)BMP+(x-x0)+L*((y-y0)/8))) >> i) & 0x01);
OLED_SetPixel(x, y+i, ((*p) >> i) & 0x01);
}
p++;
}
}
}
}
/***************************************************************
Prototype : void OLED_AreaFill(int16_t x0,int16_t y0,int16_t L,int16_t H)
Parameters : 區(qū)域內(nèi)容清除,(x0,y0)坐標(biāo)長(zhǎng)L寬H區(qū)域
0<=x0<=127 0<=y0<=63 0<=L+x0<=127 0<=H+y0<= 63 圖像取模 縱向取模,字節(jié)倒序
return : none
Description : 規(guī)定區(qū)域內(nèi)容填充
***************************************************************/
void OLED_AreaFill(int16_t x0,int16_t y0,int16_t L,int16_t H, uint8_t fill_data)
{
if (x0 >= 0 && x0 < displayWidth && x0+L <= displayWidth &&
y0 >= 0 && y0 < displayHeight && y0+H <= displayHeight) {
for(int16_t y = y0; y < y0+H; y++)
{
for(int16_t x = x0; x < x0+L; x++)
{
for(int16_t i = 0; i < 8; i++)
{
OLED_SetPixel(x, y+i, (fill_data >> i) & SET_PIXEL);
}
}
}
OLED_RefreshRAM();
}
}
/***************************************************************
Prototype : void OLED_AreaCLR(int16_t x0,int16_t y0,int16_t L,int16_t H)
Parameters : (x0,y0)坐標(biāo)長(zhǎng)L寬H區(qū)域
0<=x0<=127 0<=y0<=63 0<=L+x0<=127 0<=H+y0<= 63 圖像取模 縱向取模,字節(jié)倒序
return : none
Description : 規(guī)定區(qū)域內(nèi)容清除
***************************************************************/
void OLED_AreaClear(int16_t x0,int16_t y0,int16_t L,int16_t H)
{
if (x0 >= 0 && x0 < displayWidth && x0+L <= displayWidth &&
y0 >= 0 && y0 < displayHeight && y0+H <= displayHeight) {
for(int16_t y = y0; y < y0+H; y+=8)
{
for(int16_t x = x0; x < x0+L; x++)
{
for(int16_t i = 0; i < 8; i++)
{
OLED_SetPixel(x, y+i, RESET_PIXEL);
}
}
}
//OLED_RefreshRAM();
}
}
/***************************************************************
Prototype : void OLED_FullyToggle(void)
Parameters : none
return : none
Description : 緩沖區(qū)數(shù)據(jù)取反后刷新到GDDRAM
***************************************************************/
void OLED_FullyToggle(void)
{
for(uint16_t m = 0; m < displayHeight/8; m++)
{
for(uint16_t n = 0; n < displayWidth; n++)
{
OLED_RAM[m][n] = ~OLED_RAM[m][n];
}
}
OLED_RefreshRAM();
}
/***************************************************************
Prototype : void OLED_AreaToggle(int16_t x0,int16_t y0,int16_t L,int16_t H)
Parameters : (x0,y0)坐標(biāo)長(zhǎng)L寬H區(qū)域
0<=x0<=127 0<=y0<=63 0<=L+x0<=127 0<=H+y0<= 63 圖像取模 縱向取模,字節(jié)倒序
return : none
Description : 規(guī)定區(qū)域內(nèi)容取反
***************************************************************/
void OLED_AreaToggle(int16_t x0,int16_t y0,int16_t L,int16_t H)
{
if (x0 >= 0 && x0 < displayWidth && x0+L <= displayWidth &&
y0 >= 0 && y0 < displayHeight && y0+H <= displayHeight) {
for(int16_t y = y0; y < y0+H; y+=8)
{
for(int16_t x = x0; x < x0+L; x++)
{
for(int16_t i = 0; i < 8; i++)
{
OLED_SetPixel(x, y+i, !OLED_GetPixel(x, y+i));
}
}
}
OLED_RefreshRAM();
}
}
/****************************************************************
全屏垂直偏移,0->63方向
方向垂直向上,范圍0-63
方向垂直向下,范圍63-0
****************************************************************/
void OLED_VerticalShift(void)
{
for(uint8_t i = 0; i < displayHeight; i++)
{
WriteCmd(0xd3);//設(shè)置顯示偏移,0->63方向
WriteCmd(i);//偏移量
rt_thread_mdelay(40);//延時(shí)時(shí)間
}
}
/****************************************************************
屏幕內(nèi)容水平全屏滾動(dòng)播放
左 LEFT 0x27
右 RIGHT 0x26
****************************************************************/
void OLED_HorizontalShift(uint8_t direction)
{
WriteCmd(direction);//設(shè)置滾動(dòng)方向
WriteCmd(0x00);//虛擬字節(jié)設(shè)置,默認(rèn)為0x00
WriteCmd(0x00);//設(shè)置開始頁地址
WriteCmd(0x05);//設(shè)置每個(gè)滾動(dòng)步驟之間的時(shí)間間隔的幀頻
WriteCmd(0x07);//設(shè)置結(jié)束頁地址
WriteCmd(0x00);//虛擬字節(jié)設(shè)置,默認(rèn)為0x00
WriteCmd(0xff);//虛擬字節(jié)設(shè)置,默認(rèn)為0xff
WriteCmd(0x2f);//開啟滾動(dòng)-0x2f,禁用滾動(dòng)-0x2e,禁用需要重寫數(shù)據(jù)
}
/****************************************************************
屏幕內(nèi)容垂直水平全屏滾動(dòng)播放
上 UP 0x29
下 DOWN 0x2A
****************************************************************/
void OLED_VerticalAndHorizontalShift(uint8_t direction)
{
WriteCmd(direction);//設(shè)置滾動(dòng)方向
WriteCmd(0x00);//虛擬字節(jié)設(shè)置,默認(rèn)為0x00
WriteCmd(0x00);//設(shè)置開始頁地址
WriteCmd(0x05);//設(shè)置每個(gè)滾動(dòng)步驟之間的時(shí)間間隔的幀頻
WriteCmd(0x07);//設(shè)置結(jié)束頁地址
WriteCmd(0x01);//垂直滾動(dòng)偏移量
WriteCmd(0x2f);//開啟滾動(dòng)-0x2f,禁用滾動(dòng)-0x2e,禁用需要重寫數(shù)據(jù)
}
/****************************************************************
屏幕內(nèi)容取反顯示
開 ON 0xA7
關(guān) OFF 0xA6 默認(rèn)此模式,設(shè)置像素點(diǎn)亮
****************************************************************/
void OLED_DisplayMode(uint8_t mode)
{
WriteCmd(mode);
}
/****************************************************************
屏幕亮度調(diào)節(jié)
intensity 0-255
默認(rèn)為0x7f
****************************************************************/
void OLED_IntensityControl(uint8_t intensity)
{
WriteCmd(0x81);
WriteCmd(intensity);
}
/***************************************************************
Prototype : uint8_t GetPixel_For_Scroll(int16_t x, int16_t y, const uint8_t BMP[], uint8_t W)
Parameters : x 橫坐標(biāo)
Parameters : y 縱坐標(biāo)
Parameters : BMP[] bmp圖片(二維數(shù)組)
Parameters : W bmp圖片寬度(像素)
return : 坐標(biāo)點(diǎn)數(shù)據(jù)
Description : 獲得坐標(biāo)像素點(diǎn)數(shù)據(jù)(可以為滾動(dòng)動(dòng)畫服務(wù))
***************************************************************/
uint8_t GetPixel_For_Scroll(int16_t x, int16_t y, const uint8_t BMP[], uint8_t W)
{
uint8_t *p = (uint8_t *)BMP;
p += x + (y/8)*W;
if((*p) >> (y%8) & 0x01) return 1;
return 0;
}
/***************************************************************
Prototype : void SetPixel_for_ScrollDigit(int16_t X, int16_t Y, int16_t x, int16_t y, uint8_t set_pixel)
Parameters : X
Parameters : Y
Parameters : x
Parameters : y
Parameters : set_pixel
return : none
Description : 設(shè)置坐標(biāo)像素點(diǎn)數(shù)據(jù)(可以為滾動(dòng)動(dòng)畫服務(wù))
***************************************************************/
void SetPixel_For_Scroll(int16_t X, int16_t Y, int16_t x, int16_t y, uint8_t set_pixel)
{
if(set_pixel)
{
OLED_RAM[(Y+y)/8][X+x] |= (0x01 << ((Y+y)%8));
}
else
{
OLED_RAM[(Y+y)/8][X+x] &= ~(0x01 << ((Y+y)%8));
}
}
/****************************************************************************************************************************************************
Prototype : void Draw_Digit_BMP(uint16_t x1, uint16_t y1, const uint8_t BMP[], uint16_t Y,uint8_t W, uint8_t H, uint16_t end_line)
Parameters : x1 確定圖片顯示位置(左上角像素點(diǎn)橫坐標(biāo))
Parameters : y1 確定圖片顯示位置(左上角像素點(diǎn)縱坐標(biāo))
Parameters : BMP[] 素材圖片
Parameters : Y 所選的一幀圖片在素材圖片中的縱坐標(biāo)
Parameters : W 素材圖片寬度(也是一幀圖片的寬度)
Parameters : H 一幀圖片的高度
Parameters : end_line 在素材圖片中劃出最后一行(用于滾動(dòng)循環(huán),首尾相接)
return : none
Description : 從bmp大圖片中獲取小圖片作為滾動(dòng)動(dòng)畫的一幀圖片
*****************************************************************************************************************************************************/
void Draw_BMP_For_Scroll(uint16_t x1, uint16_t y1, const uint8_t BMP[], uint16_t Y, uint8_t W, uint8_t H, uint16_t end_line)
{
uint16_t x0,y0,y,Temp;
for(y = Y , y0 = 0 ; y0 < H ; y++ , y0++)
{
if(y > end_line) y -= (end_line+1);
for(x0 = 0; x0 < W ; x0++)
{
Temp = GetPixel_For_Scroll(x0, y, BMP, W);
SetPixel_For_Scroll(x1,y1,x0,y0,Temp);
}
}
}
2.屏幕數(shù)字滾動(dòng)
#include
uint8_t Hour=0,Minute=59,Second=55;//時(shí)間參數(shù)
uint8_t H1,H2,M1,M2,S1,S2;//時(shí)鐘時(shí)分秒六位數(shù)字
static uint16_t Y1=0,Y2=0,Y3=0,Y4=0,Y5=0,Y6=0;
static uint8_t TEMP;
void Draw_Rolling_Clock()
{
switch(H1)
{
case 0:if(Y1 < 24*2+1) Y1 = 24*2;if(Y1 < 24*2+24) Y1++;break;
case 1:
case 2:if(Y1 < H1*24-23 || Y1 > H1*24) Y1 = H1*24-24;if(Y1 < H1*24) Y1++;
}
Draw_BMP_For_Scroll(0, 16, Scroll_Digit_BMP[0], Y1, 20, 24, 2*24+23);//end_line=2*24+23,Scroll_Digit_Small_BMP劃到2*24+23行,即0~2
switch(H2)
{
case 0:
{
if(Hour == 0) {TEMP = 3;if(Y2 < 24*3+1 || Y2 > 4*24) Y2 = 24*3;if(Y2 < 24*3+24) Y2++;break;}
if(Hour == 10 || Hour == 20){TEMP = 9;if(Y2 < 24*9+1) Y2 = 24*9;if(Y2 < 24*9+24) Y2++;break;}
}
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:if(Y2 < H2*24-23 || Y2 > H2*24) Y2 = H2*24-24;if(Y2 < H2*24) Y2++;TEMP = 9;//if(Hour == 23) TEMP = 3;else TEMP = 9;
}
Draw_BMP_For_Scroll(22, 16, Scroll_Digit_BMP[0], Y2, 20, 24, TEMP*24+23);//end_line=Temp*24+23,Scroll_Digit_Small_BMP劃到Temp*24+23行,即0~Temp
switch(M1)
{
case 0:if(Y3 < 24*5+1) Y3 = 24*5;if(Y3 < 24*5+24) Y3++;break;
case 1:
case 2:
case 3:
case 4:
case 5:if(Y3 < M1*24-23 || Y3 > M1*24) Y3 = M1*24-24;if(Y3 < M1*24) Y3++;
}
Draw_BMP_For_Scroll(50, 16, Scroll_Digit_BMP[0], Y3, 20, 24, 5*24+23);//end_line=5*24+23,Scroll_Digit_Small_BMP劃到5*24+23行,即0~5
switch(M2)
{
case 0:if(Y4 < 24*9+1) Y4 = 24*9;if(Y4 < 24*9+24) Y4++;break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:if(Y4 < M2*24-23 || Y4 > M2*24) Y4 = M2*24-24;if(Y4 < M2*24) Y4++;
}
Draw_BMP_For_Scroll(72, 16, Scroll_Digit_BMP[0], Y4, 20, 24, 9*24+23);//end_line=9*24+23,Scroll_Digit_Small_BMP劃到9*24+23行,即0~9
switch(S1)
{
case 0:if(Y5 < 16*5+1) Y5 = 16*5;if(Y5 < 16*5+16) Y5++;break;
case 1:
case 2:
case 3:
case 4:
case 5:if(Y5 < S1*16-15 || Y5 > S1*16) Y5 = S1*16-16;if(Y5 < S1*16) Y5++;
}
Draw_BMP_For_Scroll(94, 24, Scroll_Digit_Small_BMP[0], Y5, 14, 16, 5*16+15);//end_line=6*16+15,Scroll_Digit_Small_BMP劃到6*16+15行,即0~6
switch(S2)
{
case 0:if(Y6 < 16*9+1) Y6 = 16*9;if(Y6 < 16*9+16) Y6++;break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:if(Y6 < S2*16-15 || Y6 > S2*16) Y6 = S2*16-16;if(Y6 < S2*16) Y6++;
}
Draw_BMP_For_Scroll(111, 24, Scroll_Digit_Small_BMP[0], Y6, 14, 16, 9*16+15);//end_line=9*16+15,Scroll_Digit_Small_BMP劃到9*16+15行,即0~9
if(Second % 2 == 1) OLED_DrawBMP(44,16,4,24,Colon_BMP[0]); //繪制冒號(hào)
else OLED_AreaClear(44,16,4,24); //清除冒號(hào)
OLED_RefreshPartRAM(2,4,0,127);
}
3.RTC獲取時(shí)間并傳遞給OLED屏(整體主函數(shù))
#include
#include
#include
#include "drv_gpio.h" //導(dǎo)入頭文件
#include "oled.h"
extern uint8_t Hour,Minute,Second;//時(shí)間參數(shù)
extern uint8_t H1,H2,M1,M2,S1,S2;//時(shí)鐘時(shí)分秒六位數(shù)字
#define LED_PIN GET_PIN(0, 0) //獲取到LED0 即P0.0的編號(hào)
time_t now;
struct tm* Inow;
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5
static rt_thread_t tid1 = RT_NULL;
/* 獲取時(shí)間線程的入口函數(shù) */
static void thread1_entry(void parameter)
{
rt_uint32_t count = 0;
/ 設(shè)置時(shí)間為11點(diǎn)15分50秒 /
set_time(20, 15, 00);
while (1)
{
/ 獲取時(shí)間 */
now = time(RT_NULL);
Inow=localtime(&now);
Hour = Inow->tm_hour;
Minute = Inow->tm_min;
Second = Inow->tm_sec;
H1=Hour/10; /* 小時(shí)的十位 */
H2=Hour%10; /* 小時(shí)的個(gè)位 */
M1=Minute/10; /* 分鐘的十位 */
M2=Minute%10; /* 分鐘的個(gè)位 */
S1=Second/10; /* 秒數(shù)的十位 */
S2=Second%10; /* 秒數(shù)的個(gè)位 */
rt_thread_mdelay(1000);
}
}
static char thread2_stack[1024];
static struct rt_thread thread2;
/* 滾動(dòng)效果線程入口 */
static void thread2_entry(void *param)
{
OLED_Init();
while(1)
{
/* 每5ms調(diào)用一次滾動(dòng)效果 */
Draw_Rolling_Clock();
rt_thread_mdelay(5);
}
}
int main(void)
{
rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); //配置為輸出模式
/* 創(chuàng)建獲取時(shí)間的線程,名稱是 thread1,入口是 thread1_entry*/
tid1 = rt_thread_create("thread1",
thread1_entry, RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY, THREAD_TIMESLICE);
/* 啟動(dòng)線程1 */
if (tid1 != RT_NULL)
rt_thread_startup(tid1);
/* 初始化線程 2,名稱是 thread2,入口是 thread2_entry */
rt_thread_init(&thread2,
"thread2",
thread2_entry,
RT_NULL,
&thread2_stack[0],
sizeof(thread2_stack),
THREAD_PRIORITY - 1, THREAD_TIMESLICE);
rt_thread_startup(&thread2);
for (;;)
{
rt_thread_mdelay(1000);
/* 展示時(shí)間 */
rt_kprintf("Hour:%d,Minute:%d,Second:%drn",Hour, Minute, Second);
}
}
評(píng)論
查看更多