慕容雪花 发表于 2025-1-10 10:53

【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;"> &nbsp;</p>

<p>引脚介绍:</p>

<p>1. GND 电源地&nbsp;<br />
2. VCC 电源正(3~5.5V)&nbsp;<br />
3. SCL OLED 的D0 脚,在IIC 通信中为时钟管脚&nbsp;<br />
4. SDA OLED 的D1 脚,在IIC 通信中为数据管脚&nbsp;</p>

<p>&nbsp;</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;"> &nbsp;</p>

<p>配置LPI2C3时钟:</p>

<p>&nbsp;</p>

<p>然后配置外设引脚:</p>

<p> &nbsp;</p>

<p>配置LPI2C3外设参数:</p>

<p> &nbsp; &nbsp;</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>&nbsp;</p>

<p><strong><span style="font-size:18px;">三、生成I2C初始化代码</span></strong></p>

<p>点击update code&nbsp;,自动生成初始化代码:</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, &amp;LPI2C3_masterConfig, LPI2C3_CLOCK_FREQ);
LPI2C_MasterTransferCreateHandle(LPI2C3_PERIPHERAL, &amp;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) &lt; 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 &lt;&lt; 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 &amp;&amp; (__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, &amp;LPI2C3_masterTransfer);
}</code></pre>

<p><span style="font-size:18px;"><strong>五、添加应用代码</strong></span></p>

<p>主函数代码:</p>

<pre>
<code>/*
* <a href="home.php?mod=space&amp;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(&quot;Hello World\r\n&quot;);
    PRINTF(&quot;CLOCK_GetCoreSysClkFreq = %8d\r\n&quot;, CLOCK_GetCoreSysClkFreq());
    PRINTF(&quot;CLOCK_GetMainClk = %8d\r\n&quot;, CLOCK_GetMainClk());
    PRINTF(&quot;CLOCK_GetSystickClkFreq = %8d\r\n&quot;, CLOCK_GetSystickClkFreq());

    OLED_Init();
    OLED_Refresh();
        OLED_Clear();
        OLED_ShowString(0, 2, &quot;NXP   2025-01-10&quot;, 8, 1);
        OLED_DrawLine(0,13, 127,13,1);
        OLED_ShowString(44, 16, &quot;10:00&quot;, 16, 1);
        OLED_ShowString(86, 24, &quot;00&quot;, 8, 1);
        OLED_DrawLine(0,33, 127,33,1);
        OLED_ShowString(0, 36, &quot;Drive by HwIIC&quot;, 8, 1);
        OLED_ShowString(0, 46, &quot;Dev Addr: 0x3C&quot;, 8, 1);
        OLED_ShowString(0, 55, &quot;Good Day&quot;, 8, 1);
        //OLED_ShowString(0, 12, &quot;WB09KE&quot;, 8, 1);
        OLED_Refresh();


    /* Force the counter to be placed into memory. */

    /* Enter an infinite loop, just incrementing a counter. */
    while(1) {
            sprintf(testValString, &quot;%2dh:%2dmin:%2ds&quot;, testVal/3600, (testVal%3600)/60, (testVal%3600)%60);
            OLED_ShowString(24, 16, testValString,12,0);
            OLED_Refresh();
    }
    return 0 ;
}
</code></pre>

<p>&nbsp;</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>

Jacktang 发表于 2025-1-11 09:44

<p>OLED在初始化的时候用到了延迟,利用上次体验的LPTMR0来制作N毫秒的延迟,这个毫秒级是个位是几十百毫秒</p>
页: [1]
查看完整版本: 【MCXA156开发板测评】-4-LPI2C驱动OLED屏幕