來源:轉(zhuǎn)載自21ic論壇極海半導(dǎo)體專區(qū)
1、前言
最近拿到了極海的APM32F411 TINY 板卡,APM32F411是其新推出的新品,資源如下:
基于Arm Cortex-M4F內(nèi)核,工作主頻120MHz,具有高速運(yùn)算能力、多種工作模式、以及豐富的高精度外設(shè)和通訊接口;內(nèi)置CRC32運(yùn)算單元,可為用戶提供高集成度、高可靠性的SoC方案;作為APM32F4系列MCU的超值型拓展產(chǎn)品,能很好的滿足用戶對(duì)功耗、性能、性價(jià)比方面的產(chǎn)品均衡需求,可適用于電力,儀器儀表,工控,家電,物聯(lián)網(wǎng),新能源,智慧樓宇等廣泛的應(yīng)用領(lǐng)域。
更多內(nèi)容可以看他們的官網(wǎng):[APM32F411 (geehy.com)](https://geehy.com/apm32?id=81)
拿到了他們的APM32F411 TINY 板卡后想著搞點(diǎn)事情,手上有一個(gè)0.96寸的OLED屏幕,想著拿這個(gè)板卡點(diǎn)亮這個(gè)屏幕,但想著點(diǎn)亮多沒意思,于是便有了這個(gè)筆記“基于APM32F411 移植 U8g2”。剛好這個(gè) TINY 板卡是沒有屏幕顯示的,后面的小伙伴也可以在我做的demo上做一些自己的應(yīng)用顯示。
那話不多說,現(xiàn)在開始吧。
2、 APM32F411 源碼準(zhǔn)備
APM32F411 的評(píng)估源碼可以在他們官網(wǎng)獲取:https://geehy.com/uploads/tool/APM32F4xx_SDK_V1.4.zip
我手上的OLED使用的是I2C進(jìn)行驅(qū)動(dòng)的,所以我這里直接在他們的“APM32F4xx_SDK_V1.4ExamplesI2C”目錄下復(fù)制“I2C_TwoBoards_Master”demo并改名為“I2C_U8g2”。
我們將在這個(gè)demo的基礎(chǔ)上實(shí)現(xiàn)U8g2適配。
3、 U8g2源碼準(zhǔn)備
U8g2的源碼在GitHub上開源:https://github.com/olikraus/u8g2
我們把它的源碼下載下來。
4、 移植U8g2至APM32F411
4.1 復(fù)制U8g2源碼
我們?cè)贏PM32F4xx_SDK_V1.4Middlewares下新建U8g2文件夾用于保存我們工程所需的U8g2源碼。
由于U8g2支持多種顯示驅(qū)動(dòng)的屏幕,因?yàn)樵创a中也包含了各個(gè)驅(qū)動(dòng)對(duì)應(yīng)的文件(所以不需要自己去寫屏幕底層驅(qū)動(dòng)了),為了減小整個(gè)工程的代碼體積,我們?cè)谝浦睻8g2時(shí),可以刪除一些對(duì)本工程來說無用的文件。
這里我們主要關(guān)注的是**U8g2庫文件**中的**csrc文件**。我們把csrc文件夾中的內(nèi)容添加入我們的APM32F4xx_SDK_V1.4MiddlewaresU8g2中。
4.2 工程包含U8g2源碼
在工程下新建“U8g2”分組用于存放U8g2源碼。
由于“u8x8_d_sxxx.c”等源碼是驅(qū)動(dòng)屏幕的驅(qū)動(dòng)文件,這里我們選用“u8x8_d_ssd1306_128x64_noname.c”,又因?yàn)閡8g2_d_memory.c,u8g2_d_setup.c是必須的驅(qū)動(dòng)函數(shù)所在文件這兩個(gè)我們保留。(即:u8x8_d_sxxx.c樣式的文件僅保留u8x8_d_ssd1306_128x64_noname.c、u8g2_d_memory.c、u8g2_d_setup.c)。
4.3 添加延時(shí)函數(shù)功能
APM32F4的SDK中已經(jīng)有一個(gè)“bsp_delay.c”文件使用滴答定時(shí)器做的延時(shí),我們包含進(jìn)工程。
包含進(jìn)工程后,我們要把“APM_DelayTickDec()”函數(shù)放置至 apm32f4xx_int.c中的滴答定時(shí)器中斷。
如此一來我們便可以正常使用“APM_DelayMs”及“APM_DelayUs”函數(shù)了。
4.4 完善I2C初始化及發(fā)送函數(shù)
由于本demo使用的是I2C的主機(jī)功能,且只需要發(fā)送功能,我們把I2C的初始化函數(shù)編寫如下:
/*!
* I2C Init
*
* @param None
*
* @retval None
*/
void I2CInit(void)
{
GPIO_Config_T gpioConfigStruct;
I2C_Config_T i2cConfigStruct;
/* Enable I2C related Clock */
RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_I2C1);
/* Free I2C_SCL and I2C_SDA */
GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_6, GPIO_AF_I2C1);
GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_7, GPIO_AF_I2C1);
gpioConfigStruct.mode = GPIO_MODE_AF;
gpioConfigStruct.speed = GPIO_SPEED_50MHz;
gpioConfigStruct.pin = GPIO_PIN_6 | GPIO_PIN_7;
gpioConfigStruct.otype = GPIO_OTYPE_OD;
gpioConfigStruct.pupd = GPIO_PUPD_NOPULL;
GPIO_Config(GPIOB, &gpioConfigStruct);
/* Config I2C1 */
I2C_Reset(I2C1);
i2cConfigStruct.mode = I2C_MODE_I2C;
i2cConfigStruct.dutyCycle = I2C_DUTYCYCLE_2;
i2cConfigStruct.ackAddress = I2C_ACK_ADDRESS_7BIT;
i2cConfigStruct.ownAddress1 = 0XA0;
i2cConfigStruct.ack = I2C_ACK_ENABLE;
i2cConfigStruct.clockSpeed = 100000;
I2C_Config(I2C1, &i2cConfigStruct);
I2C_DisableDualAddress(I2C1);
/* Enable I2Cx */
I2C_Enable(I2C1);
}
原demo是使用字符串結(jié)束符來判斷發(fā)送內(nèi)容的結(jié)束的,我們簡單修改一下發(fā)送函數(shù),傳參內(nèi)容有:
1. 目標(biāo)I2C從機(jī)地址
2. 發(fā)送數(shù)組
3. 發(fā)送數(shù)據(jù)的大小
這里我們固定I2C從機(jī)地址為7bit。
/*!
* Write data to the I2C1
*
* @param pBuffer: wiret buffer
*
* @retval 0: Error 1:Succee
*/
uint8_t I2C_Write_Buff(uint16_t DevAddress, uint8_t *pBuffer, uint16_t Size)
{
uint16_t tx_size = Size;
uint16_t I2CTimeout = I2CT_LONG_TIMEOUT;
while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET)
{
I2CInit();
if ((I2CTimeout--) == 0)
{
return I2C_TIMEOUT_UserCallback(4);
}
}
I2C_DisableInterrupt(I2C1, I2C_INT_EVT);
/* Send START condition */
I2C_EnableGenerateStart(I2C1);
I2CTimeout = I2CT_FLAG_TIMEOUT;
while (!I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) //EV5
{
if ((I2CTimeout--) == 0)
{
return I2C_TIMEOUT_UserCallback(5);
}
}
/* Send address for write */
I2C_Tx7BitAddress(I2C1, DevAddress, I2C_DIRECTION_TX);
I2CTimeout = I2CT_FLAG_TIMEOUT;
while (!I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //EV6
{
if ((I2CTimeout--) == 0)
{
return I2C_TIMEOUT_UserCallback(6);
}
}
/* While there is data to be written */
while (tx_size > 0u)
{
I2CTimeout = I2CT_LONG_TIMEOUT;
/* Send the current byte */
I2C_TxData(I2C1, *pBuffer);
while (!I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) //EV8
{
if ((I2CTimeout--) == 0)
{
return I2C_TIMEOUT_UserCallback(8);
}
}
/* Point to the next byte to be written */
pBuffer++;
tx_size --;
}
while (!I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) //EV8-2
{
if ((I2CTimeout--) == 0)
{
return I2C_TIMEOUT_UserCallback(9);
}
}
I2C_EnableGenerateStop(I2C1);
return 1;
}
4.5 修改u8g2_d_memory.c
該源文件中包含著各個(gè)屏幕的驅(qū)動(dòng)緩存,這里我們僅保留“uint8_t *u8g2_m_16_8_f(uint8_t *page_cnt)”,其他函數(shù)進(jìn)行注釋。
4.6 修改u8g2_d_setup.c
該源文件中包含著各個(gè)屏幕的驅(qū)動(dòng)緩存,這里我們僅保留“uint8_t *u8g2_m_16_8_f(uint8_t *page_cnt)”,其他函數(shù)進(jìn)行注釋。
5、 編寫u8g2初始化代碼
我們要使用u8g2需要對(duì)其進(jìn)行一些初始化操作,我們新建 一個(gè)“apm32_u8g2.c”保存這部分內(nèi)容。這里主要寫一下“u8x8_byte_hw_i2c”函數(shù)內(nèi)容,需要吧I2C初始化和I2C發(fā)送函數(shù)放在這里面。
uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
/* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
static uint8_t buffer[128];
static uint8_t buf_idx;
uint8_t *data;
switch (msg)
{
case U8X8_MSG_BYTE_INIT:
{
/* add your custom code to init i2c subsystem */
I2CInit();
}
break;
case U8X8_MSG_BYTE_START_TRANSFER:
{
buf_idx = 0;
}
break;
case U8X8_MSG_BYTE_SEND:
{
data = (uint8_t *)arg_ptr;
while (arg_int > 0)
{
buffer[buf_idx++] = *data;
data++;
arg_int--;
}
}
break;
case U8X8_MSG_BYTE_END_TRANSFER:
{
if (I2C_Write_Buff( OLED_ADDRESS, buffer, buf_idx) != 1)
return 0;
}
break;
case U8X8_MSG_BYTE_SET_DC:
break;
default:
return 0;
}
return 1;
}
6、 編寫OLED測試函數(shù)
OLED需要進(jìn)行一些測試,如畫點(diǎn),畫圓等操作,我這里寫了一個(gè)“oled_test.c”文件進(jìn)行了測試驗(yàn)證。因?yàn)檫@里面的代碼比較多就不一一說明了。
7、 最終效果
完成代碼編寫后,即可通過APM32F411TINY板卡的板載仿真器進(jìn)行程序下載啦。
程序運(yùn)行如下所示:
注:文章作者在原帖中提供了例程文件,有需要請(qǐng)至原文21ic論壇下載
原文地址:https://bbs.21ic.com/icview-3326714-1-1.html
-
mcu
+關(guān)注
關(guān)注
146文章
17981瀏覽量
366838 -
ARM
+關(guān)注
關(guān)注
134文章
9352瀏覽量
377524 -
OLED
+關(guān)注
關(guān)注
120文章
6286瀏覽量
228065 -
移植
+關(guān)注
關(guān)注
1文章
401瀏覽量
28691 -
極海半導(dǎo)體
+關(guān)注
關(guān)注
0文章
164瀏覽量
4825
原文標(biāo)題:APM32芯得 EP.61 | 基于APM32F411移植U8g2驅(qū)動(dòng)OLED完整教程
文章出處:【微信號(hào):geehysemi,微信公眾號(hào):Geehy極海半導(dǎo)體】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
極海APM32F411微控制器硬件FPU使用指南

【CH32V208開發(fā)板】圖形庫u8g2的oled顯示
U8G2庫簡介
oled—u8g2庫使用說明
【平頭哥RVB2601創(chuàng)意應(yīng)用開發(fā)】實(shí)踐2-移植U8g2圖形庫
如何使用u8g2軟件包驅(qū)動(dòng)OLED屏幕并實(shí)現(xiàn)rtc時(shí)間顯示呢
【國民技術(shù)N32項(xiàng)目移植】SPI U8G2驅(qū)動(dòng) oled 屏
esp8266學(xué)習(xí)筆記⑨:OLED 屏幕的使用(u8g2圖形庫模塊)

ESP8266驅(qū)動(dòng)SH1306-1.3寸OLED屏幕(u8g2圖形庫)

極海半導(dǎo)體推出APM32F411系列高性能高適配型MCU

關(guān)于stm32,u8g2菜單之間切換(二)u8g2的移植

評(píng)論