【MCXA156开发板测评】-4-LPI2C驱动OLED屏幕
<div class='showpostmsg'><p>在DIY小制作的时候,串口打印是查看调试信息的好方式,还可以增加一块具有I2C接口的小屏幕在板子上,展示一些数据或者打印一些调试信息,也是不错的选择。</p><div style="text-align: center;"></div>
<p>本次体验了</p>
<ul>
<li>在NXP官方IDE MCUXPRESSO中使用内置的CONFIGTOOL来配置I2C的时钟、外设参数,然后自动生成初始化代码;</li>
<li>利用上次体验的LPTMR0设计简易延迟函数</li>
<li>增加OLED驱动代码并适配MCAX156的I2C传输方式</li>
<li>成功点亮屏幕,并设计了简易计时器</li>
</ul>
<p><strong><span style="font-size:18px;"><span style="font-family:Courier;">一、OLED屏幕介绍</span></span></strong></p>
<p style="text-align: center;"> </p>
<p>引脚介绍:</p>
<p>1. GND 电源地 <br />
2. VCC 电源正(3~5.5V) <br />
3. SCL OLED 的D0 脚,在IIC 通信中为时钟管脚 <br />
4. SDA OLED 的D1 脚,在IIC 通信中为数据管脚 </p>
<p> </p>
<p>二、MCU CONFIG TOOL配置I2C</p>
<p>本次实验使用的I2C是LPI2C3,开发板已经引出SCL到Mikro BUS接口的P3_27和SDA到Mikro BUS接口的P3_28</p>
<p style="text-align: center;"> </p>
<p>配置LPI2C3时钟:</p>
<p> </p>
<p>然后配置外设引脚:</p>
<p> </p>
<p>配置LPI2C3外设参数:</p>
<p> </p>
<p>注意:</p>
<ul>
<li>上述Follower Address: 0x3C是OLED屏幕的7-bit地址,并且没有Sub-address。</li>
<li>BufferSize设置为2是对应OLED写数据是0x40 + uint8_t,写指令是0x00 + uint8_t。这两种情况都是2个byte</li>
</ul>
<p> </p>
<p><strong><span style="font-size:18px;">三、生成I2C初始化代码</span></strong></p>
<p>点击update code ,自动生成初始化代码:</p>
<pre>
<code>/***********************************************************************************************************************
* LPI2C3 initialization code
**********************************************************************************************************************/
/* clang-format off */
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
instance:
- name: 'LPI2C3'
- type: 'lpi2c'
- mode: 'master'
- custom_name_enabled: 'false'
- type_id: 'lpi2c_2.2.0'
- functional_group: 'BOARD_InitPeripherals'
- peripheral: 'LPI2C3'
- config_sets:
- main:
- clockSource: 'Lpi2cClock'
- clockSourceFreq: 'ClocksTool_DefaultInit'
- interrupt_vector: []
- master:
- mode: 'transfer'
- config:
- enableMaster: 'true'
- enableDoze: 'true'
- debugEnable: 'false'
- ignoreAck: 'false'
- pinConfig: 'kLPI2C_2PinOpenDrain'
- baudRate_Hz: '100000'
- busIdleTimeout_ns: '0'
- pinLowTimeout_ns: '0'
- sdaGlitchFilterWidth_ns: '0'
- sclGlitchFilterWidth_ns: '0'
- hostRequest:
- enable: 'false'
- source: 'kLPI2C_HostRequestExternalPin'
- polarity: 'kLPI2C_HostRequestPinActiveHigh'
- edmaRequestSources: ''
- transfer:
- blocking: 'false'
- enable_custom_handle: 'false'
- callback:
- name: ''
- userData: ''
- flags: ''
- slaveAddress: '0x3C'
- direction: 'kLPI2C_Write'
- subaddress: '0'
- subaddressSize: '0'
- blocking_buffer: 'false'
- enable_custom_buffer: 'false'
- dataSize: '2'
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
/* clang-format on */
const lpi2c_master_config_t LPI2C3_masterConfig = {
.enableMaster = true,
.enableDoze = true,
.debugEnable = false,
.ignoreAck = false,
.pinConfig = kLPI2C_2PinOpenDrain,
.baudRate_Hz = 100000UL,
.busIdleTimeout_ns = 0UL,
.pinLowTimeout_ns = 0UL,
.sdaGlitchFilterWidth_ns = 0U,
.sclGlitchFilterWidth_ns = 0U,
.hostRequest = {
.enable = false,
.source = kLPI2C_HostRequestExternalPin,
.polarity = kLPI2C_HostRequestPinActiveHigh
}
};
lpi2c_master_transfer_t LPI2C3_masterTransfer = {
.flags = kLPI2C_TransferDefaultFlag,
.slaveAddress = 0x3C,
.direction = kLPI2C_Write,
.subaddress = 0,
.subaddressSize = 0,
.data = LPI2C3_masterBuffer,
.dataSize = 2
};
lpi2c_master_handle_t LPI2C3_masterHandle;
uint8_t LPI2C3_masterBuffer;
static void LPI2C3_init(void) {
LPI2C_MasterInit(LPI2C3_PERIPHERAL, &LPI2C3_masterConfig, LPI2C3_CLOCK_FREQ);
LPI2C_MasterTransferCreateHandle(LPI2C3_PERIPHERAL, &LPI2C3_masterHandle, NULL, NULL);
}</code></pre>
<p><strong><span style="font-size:18px;">四、适配OLED驱动</span></strong></p>
<p>OLED在初始化的时候用到了延迟,利用上次体验的LPTMR0来制作N毫秒的延迟:</p>
<pre>
<code>void HAL_Delay(uint32_t N_ms){
static uint32_t i;
i = cnt;
while((cnt - i) < N_ms){
;
}
}</code></pre>
<p>cnt在LPTMR0_ISR中1ms更新一次数值:</p>
<pre>
<code>void LPTMR0_IRQHANDLER(void) {
uint32_t intStatus;
/* Reading all interrupt flags of status register */
intStatus = LPTMR_GetStatusFlags(LPTMR0_PERIPHERAL);
LPTMR_ClearStatusFlags(LPTMR0_PERIPHERAL, intStatus);
/* Place your code here */
cnt++;
if(cnt%1000 == 0){
/* Toggle pin connected to LED */
GPIO_PortToggle(GPIO3, 1u << 0);
PRINTF("\r\n GPIO3_0 RED LED TOOGLED, testVal = %d", testVal++);
}
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
Store immediate overlapping exception return operation might vector to incorrect interrupt. */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}</code></pre>
<p>这样就快速实现了N毫秒延迟。</p>
<p>接下来就是怎么把指令或者数据通过LPI2C3总线发送出去:</p>
<pre>
<code>/***************************************************
I2C总线传出数据函数:
addr: 要写入的地址(OLED的地址一般为0x40;指令地址为0x00)
data: 要写入的数据
***************************************************/
extern lpi2c_master_transfer_t LPI2C3_masterTransfer;
extern uint8_t LPI2C3_masterBuffer;
void NXP_I2C_WriteByte(uint8_t addr,uint8_t data)
{
LPI2C3_masterBuffer = addr;
LPI2C3_masterBuffer = data;
LPI2C_MasterTransferBlocking(LPI2C3_PERIPHERAL, &LPI2C3_masterTransfer);
}</code></pre>
<p><span style="font-size:18px;"><strong>五、添加应用代码</strong></span></p>
<p>主函数代码:</p>
<pre>
<code>/*
* <a href="home.php?mod=space&uid=159083" target="_blank">@brief </a> Application entry point.
*/
int main(void) {
/* Init board hardware. */
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();
//SysTick_Config(CLOCK_GetSystickClkFreq());
/* Init FSL debug console. */
BOARD_InitDebugConsole();
PRINTF("Hello World\r\n");
PRINTF("CLOCK_GetCoreSysClkFreq = %8d\r\n", CLOCK_GetCoreSysClkFreq());
PRINTF("CLOCK_GetMainClk = %8d\r\n", CLOCK_GetMainClk());
PRINTF("CLOCK_GetSystickClkFreq = %8d\r\n", CLOCK_GetSystickClkFreq());
OLED_Init();
OLED_Refresh();
OLED_Clear();
OLED_ShowString(0, 2, "NXP 2025-01-10", 8, 1);
OLED_DrawLine(0,13, 127,13,1);
OLED_ShowString(44, 16, "10:00", 16, 1);
OLED_ShowString(86, 24, "00", 8, 1);
OLED_DrawLine(0,33, 127,33,1);
OLED_ShowString(0, 36, "Drive by HwIIC", 8, 1);
OLED_ShowString(0, 46, "Dev Addr: 0x3C", 8, 1);
OLED_ShowString(0, 55, "Good Day", 8, 1);
//OLED_ShowString(0, 12, "WB09KE", 8, 1);
OLED_Refresh();
/* Force the counter to be placed into memory. */
/* Enter an infinite loop, just incrementing a counter. */
while(1) {
sprintf(testValString, "%2dh:%2dmin:%2ds", testVal/3600, (testVal%3600)/60, (testVal%3600)%60);
OLED_ShowString(24, 16, testValString,12,0);
OLED_Refresh();
}
return 0 ;
}
</code></pre>
<p> </p>
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script> <p>OLED在初始化的时候用到了延迟,利用上次体验的LPTMR0来制作N毫秒的延迟,这个毫秒级是个位是几十百毫秒</p>
页:
[1]