日B视频 亚洲,啪啪啪网站一区二区,91色情精品久久,日日噜狠狠色综合久,超碰人妻少妇97在线,999青青视频,亚洲一区二卡,让本一区二区视频,日韩网站推荐

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

瑞薩RA MCU眾測寶典 | OLED之【RA-Eco-RA2L1】I2C驅(qū)動(dòng)OLED屏幕 BME280傳感器

RA生態(tài)工作室 ? 2026-05-08 16:08 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前言


瑞薩RA MCU眾測寶典 | 串口之【RA-Eco-RA2L1】RTC日歷及串口設(shè)置時(shí)間

RA MCU眾測寶典 | PWM之【RA2L1】呼吸燈

RA MCU眾測寶典 | ADC/DAC之【RA2L1】DAC電壓輸出及ADC電壓采集實(shí)驗(yàn)

本次實(shí)驗(yàn)的目標(biāo)是把I2C相關(guān)的搞定,再嘗試驅(qū)動(dòng)SSD1306 0.96寸OLED屏幕以及BME280傳感器,最后將傳感器讀到的數(shù)據(jù)和實(shí)時(shí)時(shí)間顯示在屏幕上。


01


硬件部分


1

I2C協(xié)議簡介

I2C通訊協(xié)議(Inter-Integrated Circuit)由于它引腳少,硬件實(shí)現(xiàn)簡單,可擴(kuò)展性強(qiáng),不需要USART、CAN等通訊協(xié)議的外部收發(fā)設(shè)備,現(xiàn)在被廣泛地使用在系統(tǒng)內(nèi)多個(gè)集成電路(IC)間的通訊。


在計(jì)算機(jī)科學(xué)里,大部分復(fù)雜的問題都可以通過分層來簡化。如芯片被分為內(nèi)核層和片上外設(shè);瑞薩的FPS庫則是在寄存器與用戶代碼之間的軟件層。


對(duì)于通訊協(xié)議,我們也以分層的方式來理解,最基本的是把它分為物理層和協(xié)議層。物理層規(guī)定通訊系統(tǒng)中具有機(jī)械、電子功能部分的特性,確保原始數(shù)據(jù)在物理媒體的傳輸。協(xié)議層主要規(guī)定通訊邏輯,統(tǒng)一收發(fā)雙方的數(shù)據(jù)打包、解包標(biāo)準(zhǔn)。簡單來說物理層規(guī)定我們用嘴巴還是用肢體來交流,協(xié)議層則規(guī)定我們用中文還是英文來交流。

2

OLED屏幕

本次使用的屏幕是0.96寸4針I(yè)2C協(xié)議OLED屏幕,其驅(qū)動(dòng)IC為SSD1306,屏幕分辨率為128x64。


編程時(shí)參考的數(shù)據(jù)手冊(cè),具體的修改參考軟件部分。


3

BME280溫濕度氣壓傳感器

BME280是一款由Bosch Sensortec開發(fā)的多功能環(huán)境傳感器,可同時(shí)精確測量溫度、濕度和氣壓,具有低功耗和小尺寸的特點(diǎn),廣泛應(yīng)用于氣象監(jiān)測、室內(nèi)導(dǎo)航、健康監(jiān)測及物聯(lián)網(wǎng)等領(lǐng)域。


02


軟件部分


將先前03_RTC工程復(fù)制一份,重命名為04_OLED_BME280-I2C。


1

配置I2C

首先在e2s內(nèi)配置I2C

序號(hào)

操作

1

點(diǎn)擊界面下方標(biāo)簽欄中的Pins標(biāo)簽,進(jìn)入引腳配置界面。

2

在Pin Selection區(qū)域,展開Connectivity:I2C選項(xiàng),選擇I2C0。

3

在Pin Configuration區(qū)域,將Pin Group Selection設(shè)置為_A only,Operation Mode設(shè)置為Enabled。

4

勾選SDA0對(duì)應(yīng)的P401引腳和SCL0對(duì)應(yīng)的P400引腳。

1835308a-4ab5-11f1-ab55-92fbcf53809c.jpg

點(diǎn)擊可查看大圖


序號(hào)

操作

1

在Pin Selection區(qū)域,分別選擇P400和P401引腳。

2

將Output type設(shè)置為n-ch open drain,把P400和P401配置成開漏輸出。

184289f6-4ab5-11f1-ab55-92fbcf53809c.jpg

點(diǎn)擊可查看大圖


序號(hào)

操作

1

點(diǎn)擊界面下方標(biāo)簽欄中的Stacks標(biāo)簽,進(jìn)入堆棧配置頁面。

2

在HAL/Common Stacks區(qū)域,點(diǎn)擊New Stack按鈕。

3

在彈出菜單中,選擇Connectivity選項(xiàng)。

4

在Connectivity子菜單中,選擇I2C Master(r_iic_master)。

184ec4be-4ab5-11f1-ab55-92fbcf53809c.jpg

點(diǎn)擊可查看大圖


序號(hào)

操作

1

在HAL/Common Stacks區(qū)域,點(diǎn)擊選中g(shù)_i2c_master0 I2C Master (r_iic_master)。

2

在下方Settings設(shè)置區(qū)域的Module g_i2c_master0 I2C Master (r_iic_master)部分,將Rate設(shè)置為Fast-mode。

3

Module g_i2c_master0 I2C Master (r_iic_master)部分,設(shè)置Slave Address為0x3c。

4

Module g_i2c_master0 I2C Master (r_iic_master)部分,設(shè)置Callback為iic_callback,Interrupt Priority Level為Priority 2。

18596446-4ab5-11f1-ab55-92fbcf53809c.jpg

點(diǎn)擊可查看大圖


這里說明一下,在移植OLED驅(qū)動(dòng)庫時(shí)看到屏幕地址為0x78,即01111000,是包含讀寫位的(最低位)。而瑞薩這里是7位地址,不含讀寫位,因此要將0x78右移1位,即0x3C(0111100)。


確認(rèn)上面設(shè)置沒問題后,生成項(xiàng)目代碼。


03


編寫代碼


1

I2C通信相關(guān)

新建i2c.c和i2c.h文件。


i2c.h

左右滑動(dòng)查看完整內(nèi)容

#ifndefI2C_H_#defineI2C_H_
externvolatilebool i2c_rx_complete;externvolatilebool i2c_tx_complete;
voidi2c_wait_rx();voidi2c_wait_tx();#endif


i2c.c

滑動(dòng)查看完整內(nèi)容

#include"hal_data.h"#include"i2c.h"
volatilebool i2c_rx_complete =false;volatilebool i2c_tx_complete =false;uint16_ttimeout= 0;
voidiic_callback(i2c_master_callback_args_t *p_args){ if(p_args->event == I2C_MASTER_EVENT_RX_COMPLETE) { i2c_rx_complete =true; } elseif (p_args->event == I2C_MASTER_EVENT_TX_COMPLETE) { i2c_tx_complete =true; }}
voidi2c_wait_tx(){ timeout= 1000; while(!i2c_tx_complete &&timeout> 0) { timeout--; } i2c_tx_complete =false;}
voidi2c_wait_rx(){ timeout= 1000; while(!i2c_rx_complete &&timeout> 0) { timeout--; } i2c_rx_complete =false;}


由于瑞薩FSP庫的高集成度,我只需要編寫代碼實(shí)現(xiàn)回調(diào)函數(shù)iic_callback、等待發(fā)送函數(shù)i2c_wait_tx、等待接收i2c_wait_rx函數(shù)改變標(biāo)志位即可。


2

BME280操作相關(guān)

bme280.h

左右滑動(dòng)查看完整內(nèi)容

#ifndefBME280_H_#defineBME280_H_#include"hal_data.h"#defineBME280_ID 0x60typedefstruct{ doublehumi, temp, press; boolinitialized;} BME_Struct;
voidBME280_Get_Data(BME_Struct *bme);voidBME280_Init(BME_Struct *bme);voidBME280_Write_then_Read(uint8_t*src,uint8_twrite_bytes,uint8_t*data_dest,uint8_tread_bytes);voidBME280_Trimming_Values();doubleBME280_compensate_T_double(int32_tadc_T);doubleBME280_compensate_P_double(int32_tadc_P);doublebme280_compensate_H_double(int32_tadc_H);
#endif/* BME280_H_ */


bme280.c

#include"bme280.h"#include"hal_data.h"#include"i2c.h"
uint16_tdig_T1;int16_tdig_T2;int16_tdig_T3;uint16_tdig_P1;int16_tdig_P2;int16_tdig_P3;int16_tdig_P4;int16_tdig_P5;int16_tdig_P6;int16_tdig_P7;int16_tdig_P8;int16_tdig_P9;
int8_tdig_H1;int16_tdig_H2;int8_tdig_H3;int16_tdig_H4;int16_tdig_H5;int8_tdig_H6;
voidBME280_Write_then_Read(uint8_t*src,uint8_twrite_bytes,uint8_t*data_dest,uint8_tread_bytes){ //臨時(shí)設(shè)置I2C從機(jī)地址為0x76 g_i2c_master0.p_api->slaveAddressSet(&g_i2c_master0_ctrl,0x76, I2C_MASTER_ADDR_MODE_7BIT); g_i2c_master0.p_api->write(&g_i2c_master0_ctrl, src, write_bytes,true); i2c_wait_tx(); g_i2c_master0.p_api->read(&g_i2c_master0_ctrl, data_dest, read_bytes,false); i2c_wait_rx(); g_i2c_master0.p_api->slaveAddressSet(&g_i2c_master0_ctrl,0x3C, I2C_MASTER_ADDR_MODE_7BIT);}
voidBME280_Init(BME_Struct *bme){ uint8_treg =0xD0; uint8_twrite_settings[7] = {0x00}; uint8_tread_data; BME280_Write_then_Read(?,1, &read_data,1); if(read_data != BME280_ID) { printf("Init BME280 Failed!\n"); bme->initialized =false; return; } else { bme->initialized =true; }
write_settings[0] =0xF2;// 設(shè)置濕度采集的寄存器 0xF2 write_settings[1] =0x05;// 00000 101 濕度 oversampling x16 write_settings[2] =0xF4;// 設(shè)置溫度采集、氣壓采集、工作模式的寄存器 0xF4 write_settings[3] =0x93;// 100 100 11 溫度和氣壓 oversampling x8,模式為normal write_settings[4] =0xF5;// 配置config寄存器 write_settings[5] =0x10;// 000 100 0 0 ,配置濾波器系數(shù)為16 g_i2c_master0.p_api->slaveAddressSet(&g_i2c_master0_ctrl,0x76, I2C_MASTER_ADDR_MODE_7BIT); g_i2c_master0.p_api->write(&g_i2c_master0_ctrl, &write_settings[0],6,false); i2c_wait_tx(); g_i2c_master0.p_api->slaveAddressSet(&g_i2c_master0_ctrl,0x3C, I2C_MASTER_ADDR_MODE_7BIT); R_BSP_SoftwareDelay(2, BSP_DELAY_UNITS_MILLISECONDS); // 校準(zhǔn)數(shù)據(jù) BME280_Trimming_Values();}
voidBME280_Trimming_Values(){ uint8_tdata[33] = { 0, }; uint8_treg =0x88; BME280_Write_then_Read(?,1, &data[0],24); R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);// 適當(dāng)加延遲否則數(shù)據(jù)錯(cuò)誤 reg =0xA1; BME280_Write_then_Read(?,1, &data[24],1); R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);// 適當(dāng)加延遲否則數(shù)據(jù)錯(cuò)誤 reg =0xE1; BME280_Write_then_Read(?,1, &data[25],7); R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);// 適當(dāng)加延遲否則數(shù)據(jù)錯(cuò)誤
dig_T1 = (data[1] < dig_P1 = (data[7] < dig_H1 = data[24]; dig_H2 = (data[26] <>4)); dig_H6 = data[31];}
// Returns temperature in DegC, double precision. Output value of “51.23” equals 51.23 DegC.// t_fine carries fine temperature as global valuevolatilelongsignedint t_fine;doubleBME280_compensate_T_double(longsignedint adc_T){ doublevar1, var2, T; var1 = (((double)adc_T) /16384.0- ((double)dig_T1) /1024.0) * ((double)dig_T2); var2 = ((((double)adc_T) /131072.0- ((double)dig_T1) /8192.0) * (((double)adc_T) /131072.0- ((double)dig_T1) /8192.0)) * ((double)dig_T3); t_fine = (longsignedint)(var1 + var2); T = (var1 + var2) /5120.0; returnT;}// Returns pressure in Pa as double. Output value of “96386.2” equals 96386.2 Pa = 963.862 hPadoubleBME280_compensate_P_double(longsignedint adc_P){ doublevar1, var2, p; var1 = ((double)t_fine /2.0) -64000.0; var2 = var1 * var1 * ((double)dig_P6) /32768.0; var2 = var2 + var1 * ((double)dig_P5) *2.0; var2 = (var2 /4.0) + (((double)dig_P4) *65536.0); var1 = (((double)dig_P3) * var1 * var1 /524288.0+ ((double)dig_P2) * var1) /524288.0; var1 = (1.0+ var1 /32768.0) * ((double)dig_P1); if(var1 ==0.0) { return0;// avoid exception caused by division by zero } p =1048576.0- (double)adc_P; p = (p - (var2 /4096.0)) *6250.0/ var1; var1 = ((double)dig_P9) * p * p /2147483648.0; var2 = p * ((double)dig_P8) /32768.0; p = p + (var1 + var2 + ((double)dig_P7)) /16.0; returnp;}// Returns humidity in %rH as as double. Output value of “46.332” represents 46.332 % rHdoublebme280_compensate_H_double(longsignedint adc_H){ doublevar_H; var_H = (((double)t_fine) -76800.0); var_H = (adc_H - (((double)dig_H4) *64.0+ ((double)dig_H5) /16384.0* var_H)) * (((double)dig_H2) /65536.0* (1.0+ ((double)dig_H6) /67108864.0* var_H * (1.0+ ((double)dig_H3) /67108864.0* var_H))); var_H = var_H * (1.0- ((double)dig_H1) * var_H /524288.0); if(var_H >100.0) var_H =100.0; elseif(var_H voidBME280_Get_Data(BME_Struct *bme){ uint8_tdat[8] = {0}; uint32_tpress_t,temp_t,hum_t=0; uint8_treg =0xF7;
BME280_Write_then_Read(?,1, &dat[0],8); R_BSP_SoftwareDelay(2, BSP_DELAY_UNITS_MILLISECONDS); press_t= ((((uint32_t)dat[0] <>4)); temp_t= ((((uint32_t)dat[3] <>4)); hum_t= (((uint32_t)dat[6] < bme->temp =BME280_compensate_T_double(temp_t); bme->press =BME280_compensate_P_double(press_t) /100.0; bme->humi =bme280_compensate_H_double(hum_t);// printf("temp: %.2lf, humid: %.2lf, pressure: %.2lf\n", bme->temp, bme->humi, bme->press);}


BME280_compensate_T_double

bme280_compensate_H_double、

bme280_compensate_P_double

這三個(gè)函數(shù)分別為溫度、濕度、氣壓的補(bǔ)償算法函數(shù),借鑒了BME280官方數(shù)據(jù)手冊(cè)內(nèi)給出的參考代碼。


bme280工作流程為

步驟

內(nèi)容

1

上電初始化

2

寫入0xF2、0xF4、0xF5寄存器以設(shè)定過采樣率等參數(shù)

3

獲取校準(zhǔn)數(shù)據(jù)

4

調(diào)用BME280_Get_Data函數(shù),讀取0xF7~0xFE寄存器的數(shù)據(jù)

5

調(diào)用補(bǔ)償算法函數(shù)得到人類可讀的數(shù)值


注意

在寫入+讀取函數(shù)后記得跟1~5ms的延時(shí),再進(jìn)行下一步操作,否則會(huì)因?yàn)閎me280側(cè)的數(shù)據(jù)未準(zhǔn)備好,有極大概率讀取到錯(cuò)誤數(shù)據(jù)或讀不到數(shù)據(jù)。


3

OLED屏幕操作相關(guān)

oled.h

滑動(dòng)查看完整內(nèi)容

#ifndefOLED_H_#defineOLED_H_
#include"hal_data.h"
#defineOLED_CMD 0 // 寫命令#defineOLED_DATA 1// 寫數(shù)據(jù)voidOLED_ClearPoint(uint8_tx,uint8_ty);voidOLED_ColorTurn(uint8_ti);voidOLED_DisplayTurn(uint8_ti);voidOLED_WR_Byte(uint8_tdat,uint8_tmode);voidOLED_DisPlay_On(void);voidOLED_DisPlay_Off(void);voidOLED_Refresh(void);voidOLED_Clear(void);voidOLED_DrawPoint(uint8_tx,uint8_ty,uint8_tt);voidOLED_DrawLine(uint8_tx1,uint8_ty1,uint8_tx2,uint8_ty2,uint8_tmode);voidOLED_DrawCircle(uint8_tx,uint8_ty,uint8_tr);voidOLED_ShowChar(uint8_tx,uint8_ty,uint8_tchr,uint8_tsize1);voidOLED_ShowString(uint8_tx,uint8_ty,uint8_t*chr,uint8_tsize1);voidOLED_ShowNum(uint8_tx,uint8_ty,uint32_tnum,uint8_tlen,uint8_tsize1);voidOLED_ShowChinese(uint8_tx,uint8_ty,uint8_tnum,uint8_tsize1);voidOLED_ScrollDisplay(uint8_tnum,uint8_tspace);voidOLED_ShowPicture(uint8_tx,uint8_ty,uint8_tsizex,uint8_tsizey,uint8_tBMP[],uint8_tmode);voidOLED_Init(void);
#endif


oled.c

滑動(dòng)查看完整內(nèi)容

#include"oled.h"#include"oled_font.h"#include"i2c.h"volatileuint8_tOLED_GRAM[144][8];// 反顯函數(shù)voidOLED_ColorTurn(uint8_ti){ if(i ==0) { OLED_WR_Byte(0xA6, OLED_CMD);// 正常顯示 } if(i ==1) { OLED_WR_Byte(0xA7, OLED_CMD);// 反色顯示 }}// 屏幕旋轉(zhuǎn)180度voidOLED_DisplayTurn(uint8_ti){ if(i ==0) { OLED_WR_Byte(0xC8, OLED_CMD);// 正常顯示 OLED_WR_Byte(0xA1, OLED_CMD); } if(i ==1) { OLED_WR_Byte(0xC0, OLED_CMD);// 反轉(zhuǎn)顯示 OLED_WR_Byte(0xA0, OLED_CMD); }}// 發(fā)送一個(gè)字節(jié)// mode:數(shù)據(jù)/命令標(biāo)志 0,表示命令;1,表示數(shù)據(jù);voidOLED_WR_Byte(uint8_tdat,uint8_tmode){ uint8_tdata[2]; if(mode) { data[0] =0x40; } else { data[0] =0x00; } data[1] = dat; R_IIC_MASTER_Write(&g_i2c_master0_ctrl, data,2,false); i2c_wait_tx();}// 開啟OLED顯示voidOLED_DisPlay_On(void){ OLED_WR_Byte(0x8D, OLED_CMD);// 電荷泵使能 OLED_WR_Byte(0x14, OLED_CMD);// 開啟電荷泵 OLED_WR_Byte(0xAF, OLED_CMD);// 點(diǎn)亮屏幕}// 關(guān)閉OLED顯示voidOLED_DisPlay_Off(void){ OLED_WR_Byte(0x8D, OLED_CMD);// 電荷泵使能 OLED_WR_Byte(0x10, OLED_CMD);// 關(guān)閉電荷泵 OLED_WR_Byte(0xAE, OLED_CMD);// 關(guān)閉屏幕}// 更新顯存到OLEDvoidOLED_Refresh(void){ uint8_ti, n; for(i =0; i 0) incx =1;// 設(shè)置單步方向 elseif(delta_x ==0) incx =0;// 垂直線 else { incx =-1; delta_x = -delta_x; } if(delta_y >0) incy =1; elseif(delta_y ==0) incy =0;// 水平線 else { incy =-1; delta_y = -delta_x; } if(delta_x > delta_y) distance = delta_x;// 選取基本增量坐標(biāo)軸 else distance = delta_y; for(t =0; t < distance +?1; t++)? ? {? ? ? ? OLED_DrawPoint(uRow, uCol, mode);?// 畫點(diǎn)? ? ? ? xerr += delta_x;? ? ? ? yerr += delta_y;? ? ? ? if?(xerr > distance) { xerr -= distance; uRow += incx; } if(yerr > distance) { yerr -= distance; uCol += incy; } } // OLED_Refresh();}// x,y:圓心坐標(biāo)// r:圓的半徑voidOLED_DrawCircle(uint8_tx,uint8_ty,uint8_tr){ inta, b, num; a =0; b = r; while(2* b * b >= r * r) { OLED_DrawPoint(x + a, y - b,1); OLED_DrawPoint(x - a, y - b,1); OLED_DrawPoint(x - a, y + b,1); OLED_DrawPoint(x + a, y + b,1); OLED_DrawPoint(x + b, y + a,1); OLED_DrawPoint(x + b, y - a,1); OLED_DrawPoint(x - b, y - a,1); OLED_DrawPoint(x - b, y + a,1); a++; num = (a * a + b * b) - r * r;// 計(jì)算畫的點(diǎn)離圓心的距離 if(num >0) { b--; a--; } } // OLED_Refresh();}// 顯示字符 不建議直接使用,若要使用需要加上OLED_Refresh();更新到顯存voidOLED_ShowChar(uint8_tx,uint8_ty,uint8_tchr,uint8_tsize1){ uint8_ti, m, temp, size2, chr1; uint8_tx0 = x, y0 = y; // 計(jì)算字符的字節(jié)數(shù) if(size1 ==8) size2 =6; else size2 = (size1 /8+ ((size1 %8) ?1:0)) * (size1 /2);// 字體占用的字節(jié)數(shù) chr1 = chr -' ';// 偏移字符值,轉(zhuǎn)換為數(shù)組索引 for(i =0; i < size2; i++)? ? {? ? ? ? // 根據(jù)字體大小選擇相應(yīng)的字模? ? ? ? if?(size1 ==?8)? ? ? ? {? ? ? ? ? ? temp = asc2_0806[chr1][i];? ? ? ? }? ? ? ? elseif?(size1 ==?12)? ? ? ? {? ? ? ? ? ? temp = asc2_1206[chr1][i];? ? ? ? }? ? ? ? elseif?(size1 ==?16)? ? ? ? {? ? ? ? ? ? temp = asc2_1608[chr1][i];? ? ? ? }? ? ? ? elseif?(size1 ==?24)? ? ? ? {? ? ? ? ? ? temp = asc2_2412[chr1][i];? ? ? ? }? ? ? ? else? ? ? ? {? ? ? ? ? ? return;?// 字體不支持? ? ? ? }? ? ? ? for?(m =?0; m >=1; y++; } x++; if((size1 !=8) && ((x - x0) == size1 /2)) { x = x0; y0 = y0 +8; } y = y0; }}// 顯示字符串// x,y:起點(diǎn)坐標(biāo)// size1:字體大小//*chr:字符串起始地址voidOLED_ShowString(uint8_tx,uint8_ty,uint8_t*chr,uint8_tsize1){ while((*chr >=' ') && (*chr <=?'~'))?// 判斷是不是非法字符!? ? {? ? ? ? OLED_ShowChar(x, y, *chr, size1);? ? ? ? if?(size1 ==?8)? ? ? ? ? ? x +=?6;? ? ? ? else? ? ? ? ? ? x += size1 /?2;? ? ? ? chr++;? ? }? ? OLED_Refresh();}// m^nuint32_tOLED_Pow(uint8_t?m,?uint8_t?n){? ? uint32_t?result =?1;? ? while?(n--)? ? {? ? ? ? result *= m;? ? }? ? return?result;}// 顯示數(shù)字// x,y :起點(diǎn)坐標(biāo)// num :要顯示的數(shù)字// len :數(shù)字的位數(shù)// size:字體大小voidOLED_ShowNum(uint8_t?x,?uint8_t?y,?uint32_t?num,?uint8_t?len,?uint8_t?size1){? ? uint8_t?t, temp, m =?0;? ? if?(size1 ==?8)? ? ? ? m =?2;? ? for?(t =?0; t < len; t++)? ? {? ? ? ? temp = (num /?OLED_Pow(10, len - t -?1)) %?10;? ? ? ? if?(temp ==?0)? ? ? ? {? ? ? ? ? ? OLED_ShowChar(x + (size1 /?2?+ m) * t, y,?'0', size1);? ? ? ? }? ? ? ? else? ? ? ? {? ? ? ? ? ? OLED_ShowChar(x + (size1 /?2?+ m) * t, y, temp +?'0', size1);? ? ? ? }? ? }? ? OLED_Refresh();}voidOLED_ShowChinese(uint8_t?x,?uint8_t?y,?uint8_t?num,?uint8_t?size1){? ? uint8_t?m, temp;? ? uint8_t?x0 = x, y0 = y;? ? uint16_t?i, size3 = (size1 /?8?+ ((size1 %?8) ??1?:?0)) * size1;?// 計(jì)算一個(gè)字符對(duì)應(yīng)的字節(jié)數(shù)? ? uint8_t?mask; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 用來構(gòu)造顯示的掩碼? ? for?(i =?0; i < size3; i++)? ? {? ? ? ? if?(size1 ==?16)? ? ? ? {? ? ? ? ? ? temp = Hzk1[num][i];?// 獲取字形數(shù)據(jù)? ? ? ? }? ? ? ? else? ? ? ? {? ? ? ? ? ? return;?// 只處理 16x16 字體? ? ? ? }? ? ? ? for?(m =?0; m >=1;// 右移,處理下一個(gè)像素 y++; // 縱向位置移動(dòng) } x++;// 橫向位置移動(dòng) // 判斷是否換行 if((x - x0) == size1) { x = x0; y0 = y0 +8;// 換行時(shí),y 坐標(biāo)增加 8 } y = y0;// 恢復(fù) y 坐標(biāo) } // 最后刷新整個(gè)顯示屏 OLED_Refresh();}// num 顯示漢字的個(gè)數(shù)// space 每一遍顯示的間隔voidOLED_ScrollDisplay(uint8_tnum,uint8_tspace){ uint8_ti, n, t =0, m =0, r; while(1) { if(m ==0) { OLED_ShowChinese(128,24, t,16);// 寫入一個(gè)漢字保存在OLED_GRAM[][]數(shù)組中 t++; } if(t == num) { for(r =0; r >=1; y++; } x++; if((x - x0) == sizex) { x = x0; y0 = y0 +8; } y = y0; } } OLED_Refresh();}// OLED的初始化voidOLED_Init(void){ OLED_WR_Byte(0xAE, OLED_CMD);//--turn off oled panel 關(guān)閉顯示 OLED_WR_Byte(0x00, OLED_CMD);//---set low column address OLED_WR_Byte(0x10, OLED_CMD);//---set high column address OLED_WR_Byte(0x40, OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F) OLED_WR_Byte(0x81, OLED_CMD);//--set contrast control register OLED_WR_Byte(0xCF, OLED_CMD);// Set SEG Output Current Brightness OLED_WR_Byte(0xA1, OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常 OLED_WR_Byte(0xC8, OLED_CMD);// Set COM/Row Scan Direction 0xc0上下反置 0xc8正常 OLED_WR_Byte(0xA6, OLED_CMD);//--set normal display OLED_WR_Byte(0xA8, OLED_CMD);//--set multiplex ratio(1 to 64) 設(shè)置驅(qū)動(dòng)路數(shù) OLED_WR_Byte(0x3f, OLED_CMD);//--1/64 duty OLED_WR_Byte(0xD3, OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F) OLED_WR_Byte(0x00, OLED_CMD);//-not offset OLED_WR_Byte(0xd5, OLED_CMD);//--set display clock divide ratio/oscillator frequency OLED_WR_Byte(0x80, OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec OLED_WR_Byte(0xD9, OLED_CMD);//--set pre-charge period OLED_WR_Byte(0xF1, OLED_CMD);// Set Pre-Charge as 15 Clocks & Discharge as 1 Clock OLED_WR_Byte(0xDA, OLED_CMD);//--set com pins hardware configuration OLED_WR_Byte(0x12, OLED_CMD); OLED_WR_Byte(0xDB, OLED_CMD);//--set vcomh OLED_WR_Byte(0x30, OLED_CMD);// Set VCOM Deselect Level OLED_WR_Byte(0x20, OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02) OLED_WR_Byte(0x02, OLED_CMD);// OLED_WR_Byte(0x8D, OLED_CMD);//--set Charge Pump enable/disable OLED_WR_Byte(0x14, OLED_CMD);//--set(0x10) disable OLED_Clear(); OLED_WR_Byte(0xAF, OLED_CMD);}


tip

最開始OLED屏幕上顯示字的速度非常慢,幾乎是一個(gè)字一個(gè)字地往外蹦。


解決方法是開一個(gè)顯存數(shù)組OLED_GRAM,將內(nèi)容先緩存到顯存數(shù)組,再調(diào)用OLED_Refresh一次性地寫給OLED屏幕控制器。


4

修改hal_entry.c

在hal_entry.c開頭加入:

左右滑動(dòng)查看完整內(nèi)容

#include"hal_data.h"#include"debug_bsp_uart.h"#include"oled.h"#include"bme280.h"#include"rtc.h"#include
BME_Struct bme = {0,0,0,false};rtc_time_tget_time;


在hal_entry函數(shù)中加入:

滑動(dòng)查看完整內(nèi)容

Debug_UART9_Init();//SCI9 UART 調(diào)試串口初始化 g_i2c_master0.p_api->open(&g_i2c_master0_ctrl, &g_i2c_master0_cfg); BME280_Init(&bme); OLED_Init(); RTC_Init(); printf("I2C OLED屏幕+BME280獲取溫濕度實(shí)驗(yàn)\n"); printf("若要通過串口設(shè)置時(shí)間,請(qǐng)輸入類似time:20250126080910的字符串\n"); while(1) { uint8_t t1[50] ={0}, t2[50] ={0}, t3[50] ={0}, t4[50] ={0}; if(rtc_flag) { g_rtc0.p_api->calendarTimeGet(&g_rtc0_ctrl, &get_time);//獲取 RTC 計(jì)數(shù)時(shí)間 rtc_flag =0;// printf("%d年%d月%d日%d:%d:%d\n",// get_time.tm_year +1900, get_time.tm_mon +1, get_time.tm_mday,// get_time.tm_hour, get_time.tm_min, get_time.tm_sec);
sprintf((char *)t1,"%4d.%02d.%02d", get_time.tm_year +1900, get_time.tm_mon +1, get_time.tm_mday); sprintf((char *)t2,"%02d:%02d:%02d", get_time.tm_hour, get_time.tm_min, get_time.tm_sec);
if(bme.initialized) { BME280_Get_Data(&bme); sprintf((char *)t3,"%.1fC%.1f%%RH", bme.temp, bme.humi); sprintf((char *)t4,"%.1fhPa", bme.press); OLED_ShowString(12,32, t3,16);//顯示溫度濕度 OLED_ShowString(24,48, t4,16);//顯示氣壓 } OLED_ShowString(24,0, t1,16); //顯示年月日 OLED_ShowString(32,16, t2,16);//顯示時(shí)分秒
} if(uart_rx_complete_flag) { char *time; uart_rx_complete_flag =0; //解析設(shè)置時(shí)間的命令 e.g:time:20250126080910 // warning: 未添加錯(cuò)誤糾正算法,請(qǐng)輸入正確的時(shí)間,否則工作異常! if(strncmp(rx_data,"time:",5) ==0) { time= rx_data +5; set_time.tm_year = ((time[0] -'0') *1000) + ((time[1] -'0') *100) + ((time[2] -'0') *10) + (time[3] -'0') -1900; set_time.tm_mon = ((time[4] -'0') *10) + (time[5] -'0') -1; set_time.tm_mday = ((time[6] -'0') *10) + (time[7] -'0'); set_time.tm_hour = ((time[8] -'0') *10) + (time[9] -'0'); set_time.tm_min = ((time[10] -'0') *10) + (time[11] -'0'); set_time.tm_sec = ((time[12] -'0') *10) + (time[13] -'0'); g_rtc0.p_api->calendarTimeSet(&g_rtc0_ctrl, &set_time); } else{ printf("若要通過串口設(shè)置時(shí)間,請(qǐng)輸入類似time:20250126080910的字符串\n"); } } }


這段程序?qū)崿F(xiàn)了每1秒刷新一次OLED屏幕上的時(shí)間和溫濕度氣壓數(shù)據(jù),同時(shí)能從串口接收格式化的數(shù)據(jù)以設(shè)定時(shí)間。


04


下載測試


把編譯好的程序下載到開發(fā)板并復(fù)位。觀察到OLED屏幕上正確顯示了預(yù)設(shè)的時(shí)間和獲取到的溫濕度氣壓值。


可以打開串口助手,在發(fā)送框輸入time:20250128235958。


05


工程附件



(可以點(diǎn)擊“閱讀原文”或掃描下方二維碼/復(fù)制下方鏈接到瀏覽器下載附件查看完整代碼)


工程附件—OLED

https://bbs.elecfans.com/jishu_2474903_1_1.html

186673c0-4ab5-11f1-ab55-92fbcf53809c.png18774ef2-4ab5-11f1-ab55-92fbcf53809c.png

圖片演示


OLED專題還會(huì)帶來更多玩法:漢字顯示、圖片動(dòng)畫、菜單界面、多級(jí)頁面交互等。


如果你在驅(qū)動(dòng)移植、I2C地址、傳感器數(shù)據(jù)補(bǔ)償上遇到問題,歡迎在評(píng)論區(qū)交流~



聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 傳感器
    +關(guān)注

    關(guān)注

    2578

    文章

    55610

    瀏覽量

    794418
  • mcu
    mcu
    +關(guān)注

    關(guān)注

    147

    文章

    19174

    瀏覽量

    404926
  • 瑞薩
    +關(guān)注

    關(guān)注

    38

    文章

    22526

    瀏覽量

    91414
  • OLED屏幕
    +關(guān)注

    關(guān)注

    3

    文章

    208

    瀏覽量

    29582
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    RA2L1 MCU e2 studio和FSP的使用指南

    本期“RA MCU寶典” 繼續(xù)聚焦 “環(huán)境搭建” 專題,帶大家走進(jìn)【RA-Eco-RA2L1-48PIN-V1.0】的世界,查看e2 s
    的頭像 發(fā)表于 08-04 13:45 ?3261次閱讀
    <b class='flag-5'>瑞</b><b class='flag-5'>薩</b><b class='flag-5'>RA2L1</b> <b class='flag-5'>MCU</b> e2 studio和FSP的使用指南

    RA MCU寶典 | I2C讀取EEPROM

    “RAMCU寶典”IIC專題繼續(xù)深耕!上一期我們用【RA-Eco-RA2E1】開發(fā)板實(shí)現(xiàn)了IIC通信的OLED顯示。這次我們把目光轉(zhuǎn)向?qū)嵱玫拇鎯?chǔ)場景——基于【
    的頭像 發(fā)表于 01-13 18:05 ?8466次閱讀
    <b class='flag-5'>RA</b> <b class='flag-5'>MCU</b><b class='flag-5'>眾</b>測<b class='flag-5'>寶典</b> | <b class='flag-5'>I</b>2<b class='flag-5'>C</b>讀取EEPROM

    RA MCU寶典 | SPI驅(qū)動(dòng)TFT屏幕

    “RAMCU寶典”SPI專題來啦!這次我們聚焦【RA-Eco-RA4E2】開發(fā)板,一步步用SPI驅(qū)動(dòng)1.8寸TFT屏幕。開啟
    的頭像 發(fā)表于 02-03 17:02 ?7833次閱讀
    <b class='flag-5'>RA</b> <b class='flag-5'>MCU</b><b class='flag-5'>眾</b>測<b class='flag-5'>寶典</b> | SPI<b class='flag-5'>驅(qū)動(dòng)</b>TFT<b class='flag-5'>屏幕</b>

    RA MCU寶典 | 環(huán)境搭建RA-Eco-RA6E2-64PIN-V1.0 開發(fā)板】介紹、環(huán)境搭建、工程測試

    “RAMCU寶典”環(huán)境搭建專題再添實(shí)用干貨!這次咱們聚焦高性能入門級(jí)開發(fā)板——【RA-Eco-RA6E2-64PIN-V1.0】。本文介紹了RA-Eco-RA6E2-64PIN-V
    的頭像 發(fā)表于 03-20 16:23 ?7992次閱讀
    <b class='flag-5'>瑞</b><b class='flag-5'>薩</b><b class='flag-5'>RA</b> <b class='flag-5'>MCU</b><b class='flag-5'>眾</b>測<b class='flag-5'>寶典</b> | 環(huán)境搭建<b class='flag-5'>之</b>【<b class='flag-5'>RA-Eco-RA6E2</b>-64PIN-V1.0 開發(fā)板】介紹、環(huán)境搭建、工程測試

    RA MCU寶典 | 環(huán)境搭建RA-Eco-RA4M2】搭建Keil開發(fā)環(huán)境

    “RAMCU寶典”環(huán)境搭建專題再添硬核實(shí)操!開啟寶典概覽
    的頭像 發(fā)表于 04-03 17:59 ?7166次閱讀
    <b class='flag-5'>瑞</b><b class='flag-5'>薩</b><b class='flag-5'>RA</b> <b class='flag-5'>MCU</b><b class='flag-5'>眾</b>測<b class='flag-5'>寶典</b> | 環(huán)境搭建<b class='flag-5'>之</b>【<b class='flag-5'>RA-Eco-RA4M2</b>】搭建Keil開發(fā)環(huán)境

    RA MCU寶典 | 環(huán)境搭建RA-Eco-RA4M2】QE工具使用

    “RAMCU寶典”環(huán)境搭建專題再添硬核實(shí)操!開啟寶典01簡介RA-Eco-RA4M2-1
    的頭像 發(fā)表于 04-10 18:26 ?5914次閱讀
    <b class='flag-5'>瑞</b><b class='flag-5'>薩</b><b class='flag-5'>RA</b> <b class='flag-5'>MCU</b><b class='flag-5'>眾</b>測<b class='flag-5'>寶典</b> | 環(huán)境搭建<b class='flag-5'>之</b>【<b class='flag-5'>RA-Eco-RA4M2</b>】QE工具使用

    RA MCU寶典 | 串口RA-Eco-RA2L1】RTC日歷及串口設(shè)置時(shí)間

    “RAMCU寶典”串口專題添硬核實(shí)操!開啟寶典前言RAMCU
    的頭像 發(fā)表于 04-21 18:07 ?7116次閱讀
    <b class='flag-5'>瑞</b><b class='flag-5'>薩</b><b class='flag-5'>RA</b> <b class='flag-5'>MCU</b><b class='flag-5'>眾</b>測<b class='flag-5'>寶典</b> | 串口<b class='flag-5'>之</b>【<b class='flag-5'>RA-Eco-RA2L1</b>】RTC日歷及串口設(shè)置時(shí)間

    RA2L1入門學(xué)習(xí)】開箱+Keil環(huán)境搭建+點(diǎn)燈+點(diǎn)亮OLED

    );// 拉低 P104 在 main 函數(shù)調(diào)用的 hal_entry 函數(shù)里添加以上代碼即可 【點(diǎn)亮OLED顯示屏】 RA2L1 支持硬件
    發(fā)表于 01-25 12:10

    RA2L1入門學(xué)習(xí)】04、I2C驅(qū)動(dòng)OLED屏幕 BME280傳感器

    1.前言 本次實(shí)驗(yàn)的目標(biāo)是把I2C相關(guān)的搞定,再嘗試驅(qū)動(dòng)SSD1306 0.96寸OLED屏幕以及BME
    發(fā)表于 01-29 17:09

    RA-Eco-RA2E1-V1.0開發(fā)板試用】+ OLED顯示ADC采樣數(shù)據(jù)

    ,LPACMP,溫度傳感器32 位通用 PWM 定時(shí),16 位通用 PWM 定時(shí),低功耗異步通用定時(shí)實(shí)時(shí)時(shí)鐘SCI(UART、簡單 SPI、簡單
    發(fā)表于 02-02 09:21

    RA MCU創(chuàng)意氛圍賽】3. 硬件I2C驅(qū)動(dòng)OLED顯示漢字

    RA MCU創(chuàng)意氛圍賽】1. PWM驅(qū)動(dòng)LED以及STLINK下載配置【
    發(fā)表于 05-26 14:06

    CPK-RA2L1評(píng)估板I2C點(diǎn)亮OLED

    本篇文章主要介紹使用RT-Thread Studio 和 CPK-RA2L1評(píng)估板,使用大佬的輪子來點(diǎn)亮0.96寸 OLED ssd1306,
    發(fā)表于 10-11 10:54 ?1367次閱讀
    CPK-<b class='flag-5'>RA2L1</b>評(píng)估板<b class='flag-5'>I2C</b>點(diǎn)亮<b class='flag-5'>OLED</b>

    RA2L1/RA2E1 原理圖 PCB

    資料介紹 RA-Eco-RA2L1/RA2E1-48PIN-V1.0 原理圖 PCB
    發(fā)表于 10-16 00:30 ?93次下載

    RA MCU寶典 | IICRA2E1】IIC通信的OLED顯示

    “RAMCU寶典”IIC專題上線啦!這次,嵌入式小百科將和大家一起聚焦【
    的頭像 發(fā)表于 01-01 10:04 ?3533次閱讀
    <b class='flag-5'>RA</b> <b class='flag-5'>MCU</b><b class='flag-5'>眾</b>測<b class='flag-5'>寶典</b> | IIC<b class='flag-5'>之</b>【<b class='flag-5'>RA2E1</b>】IIC通信的<b class='flag-5'>OLED</b>顯示

    RA MCU寶典 | 環(huán)境搭建【FPB-RA0E2】開發(fā)環(huán)境搭建

    RA生態(tài)工作室關(guān)注我們“RAMCU寶典”環(huán)境搭建專題更新啦!這次我們聚焦【FPB-RA0E2】開發(fā)板,一步步打通開發(fā)“第一關(guān)”,為后續(xù)功能開發(fā)筑牢基礎(chǔ)。開啟
    的頭像 發(fā)表于 03-11 16:33 ?1443次閱讀
    <b class='flag-5'>RA</b> <b class='flag-5'>MCU</b><b class='flag-5'>眾</b>測<b class='flag-5'>寶典</b> | 環(huán)境搭建<b class='flag-5'>之</b>【FPB-<b class='flag-5'>RA0E2</b>】開發(fā)環(huán)境搭建
    兴山县| 雷波县| 天水市| 东阳市| 凤山县| 宜良县| 余江县| 靖边县| 桐庐县| 潞城市| 温泉县| 湖口县| 桑日县| 黑河市| 基隆市| 沽源县| 临颍县| 长治市| 合肥市| 长顺县| 嘉义市| 灌南县| 淮北市| 北票市| 高邑县| 秀山| 拉孜县| 梧州市| 伊宁市| 新龙县| 嘉鱼县| 五华县| 青铜峡市| 称多县| 英山县| 大同市| 罗江县| 谢通门县| 沈丘县| 西乌| 甘德县|