TL-LED 发表于 2023-11-2 17:43

【MSPM0L1306 LaunchPad】i2c驱动OLED显示

<p><span style="font-size:16px;">这篇来学习下使用MSPM0L1306开发板驱动OLED显示。</span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><strong>一、硬件部分</strong></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">1.1、芯片内部框图</span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">L1306芯片内部有两路I2C接口</span></p>

<p><span style="font-size:16px;"></span></p>

<p><span style="font-size:16px;">1.2、引脚配置</span></p>

<p><span style="font-size:16px;">测试使用I2C0端口,使用的引脚是PA1和PA10</span></p>

<p><span style="font-size:16px;"></span></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><strong>二、程序</strong></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">2.1、i2c.c</span></p>

<pre>
<code>#include "ti_msp_dl_config.h"
#include "i2c/i2c.h"
static const DL_I2C_ClockConfig gI2C_0ClockConfig =
{
    .clockSel = DL_I2C_CLOCK_BUSCLK,
    .divideRatio = DL_I2C_CLOCK_DIVIDE_1,
};

SYSCONFIG_WEAK void SYSCFG_DL_I2C_0_init(void)
{
        DL_I2C_setClockConfig(I2C_0_INST,(DL_I2C_ClockConfig *) &amp;gI2C_0ClockConfig);
        DL_I2C_setAnalogGlitchFilterPulseWidth(I2C_0_INST, DL_I2C_ANALOG_GLITCH_FILTER_WIDTH_50NS);
        DL_I2C_enableAnalogGlitchFilter(I2C_0_INST);

        /* Configure Controller Mode */
        DL_I2C_resetControllerTransfer(I2C_0_INST);
        /* Set frequency to 400000 Hz*/
        DL_I2C_setTimerPeriod(I2C_0_INST, 7);
        DL_I2C_setControllerTXFIFOThreshold(I2C_0_INST, DL_I2C_TX_FIFO_LEVEL_EMPTY);
        DL_I2C_setControllerRXFIFOThreshold(I2C_0_INST, DL_I2C_RX_FIFO_LEVEL_BYTES_1);
        DL_I2C_enableControllerClockStretching(I2C_0_INST);

        /* Enable module */
        DL_I2C_enableController(I2C_0_INST);
}

void init_i2c(void)
{
        DL_I2C_reset(I2C_0_INST);
        DL_I2C_enablePower(I2C_0_INST);
       
        DL_GPIO_initPeripheralInputFunctionFeatures(GPIO_I2C_0_IOMUX_SDA,
                        GPIO_I2C_0_IOMUX_SDA_FUNC, DL_GPIO_INVERSION_DISABLE,
                        DL_GPIO_RESISTOR_NONE, DL_GPIO_HYSTERESIS_DISABLE,
                        DL_GPIO_WAKEUP_DISABLE);
        DL_GPIO_initPeripheralInputFunctionFeatures(GPIO_I2C_0_IOMUX_SCL,
                        GPIO_I2C_0_IOMUX_SCL_FUNC, DL_GPIO_INVERSION_DISABLE,
                        DL_GPIO_RESISTOR_NONE, DL_GPIO_HYSTERESIS_DISABLE,
                        DL_GPIO_WAKEUP_DISABLE);
        DL_GPIO_enableHiZ(GPIO_I2C_0_IOMUX_SDA);
        DL_GPIO_enableHiZ(GPIO_I2C_0_IOMUX_SCL);
       
        SYSCFG_DL_I2C_0_init();
}

</code></pre>

<p>&nbsp;</p>

<p><span style="font-size:16px;">2.2、i2c.h</span></p>

<pre>
<code>#ifndef _I2C_H
#define _I2C_H

#include &lt;ti/driverlib/driverlib.h&gt;

/* Defines for I2C_0 */
#define I2C_0_INST                                                          I2C0
#define I2C_0_INST_IRQHandler                                    I2C0_IRQHandler
#define I2C_0_INST_INT_IRQN                                        I2C0_INT_IRQn
#define I2C_0_BUS_SPEED_HZ                                                400000
#define GPIO_I2C_0_SDA_PORT                                                GPIOA
#define GPIO_I2C_0_SDA_PIN                                        DL_GPIO_PIN_10
#define GPIO_I2C_0_IOMUX_SDA                                     (IOMUX_PINCM11)
#define GPIO_I2C_0_IOMUX_SDA_FUNC                      IOMUX_PINCM11_PF_I2C0_SDA
#define GPIO_I2C_0_SCL_PORT                                                GPIOA
#define GPIO_I2C_0_SCL_PIN                                       DL_GPIO_PIN_1
#define GPIO_I2C_0_IOMUX_SCL                                    (IOMUX_PINCM2)
#define GPIO_I2C_0_IOMUX_SCL_FUNC                     IOMUX_PINCM2_PF_I2C0_SCL

void init_i2c(void);

#endif
</code></pre>

<p>&nbsp;</p>

<p><span style="font-size:16px;">2.3、oled.c</span></p>

<pre>
<code>#include "ti_msp_dl_config.h"
#include "i2c/i2c.h"
#include "oled/oled.h"
#include "oled/codetab.h"
#include &lt;stdio.h&gt;
#include "systick/systick.h"

void I2C_WriteByte(uint8_t addr, uint8_t dat)
{
uint8_t temp;
temp = addr;
temp = dat;
       
DL_I2C_fillControllerTXFIFO(I2C_0_INST, temp, 2);
while (!(DL_I2C_getControllerStatus(I2C_0_INST) &amp; DL_I2C_CONTROLLER_STATUS_IDLE));

        DL_I2C_startControllerTransfer(I2C_0_INST, OLED_ADDRESS, DL_I2C_CONTROLLER_DIRECTION_TX, 2);
        while (DL_I2C_getControllerStatus(I2C_0_INST) &amp; DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
        while (!(DL_I2C_getControllerStatus(I2C_0_INST) &amp; DL_I2C_CONTROLLER_STATUS_IDLE));
        DL_I2C_flushControllerTXFIFO(I2C_0_INST);
}


void WriteCmd(unsigned char I2C_Command)
{
    I2C_WriteByte(0x00, I2C_Command);
}

void WriteDat(unsigned char I2C_Data)
{
    I2C_WriteByte(0x40, I2C_Data);
}

void OLED_WrCmd(unsigned char IIC_Command)
{
        WriteCmd(IIC_Command);
}

void OLED_Init(void)
{
        SysTick_Delay_ms(100);
        WriteCmd(0xAE); //display off
        WriteCmd(0x20);        //Set Memory Addressing Mode       
        WriteCmd(0x10);        //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
        WriteCmd(0xb0);        //Set Page Start Address for Page Addressing Mode,0-7
        WriteCmd(0xc8);        //Set COM Output Scan Direction
        WriteCmd(0x00); //---set low column address
        WriteCmd(0x10); //---set high column address
        WriteCmd(0x40); //--set start line address
        WriteCmd(0x81); //--set contrast control register
        WriteCmd(0xff); //ÁÁ¶Èµ÷½Ú 0x00~0xff
        WriteCmd(0xa1); //--set segment re-map 0 to 127
        WriteCmd(0xa6); //--set normal display
        WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
        WriteCmd(0x3F); //
        WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
        WriteCmd(0xd3); //-set display offset
        WriteCmd(0x00); //-not offset
        WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
        WriteCmd(0xf0); //--set divide ratio
        WriteCmd(0xd9); //--set pre-charge period
        WriteCmd(0x22); //
        WriteCmd(0xda); //--set com pins hardware configuration
        WriteCmd(0x12);
        WriteCmd(0xdb); //--set vcomh
        WriteCmd(0x40); //0x20,0.77xVcc
        WriteCmd(0x8d); //--set DC-DC enable
        WriteCmd(0x14); //
        WriteCmd(0xaf); //--turn on oled panel
}

void OLED_SetPos(unsigned char x, unsigned char y)
{
        WriteCmd(0xb0+y);
        WriteCmd(((x&amp;0xf0)&gt;&gt;4)|0x10);
        WriteCmd((x&amp;0x0f)|0x01);
}

void OLED_Fill(unsigned char fill_Data)//È«ÆÁÌî³ä
{
        unsigned char m,n;
        for(m=0;m&lt;8;m++)
        {
                WriteCmd(0xb0+m);                //page0-page1
                WriteCmd(0x00);                //low column start address
                WriteCmd(0x10);                //high column start address
                for(n=0;n&lt;128;n++)
                        {
                                WriteDat(fill_Data);
                        }
        }
}

void OLED_CLS(void)//ÇåÆÁ
{
        OLED_Fill(0xff);
}

void OLED_ON(void)
{
        WriteCmd(0X8D);//ÉèÖõçºÉ±Ã
        WriteCmd(0X14);//¿ªÆôµçºÉ±Ã
        WriteCmd(0XAF);//OLED»½ÐÑ
}

void OLED_OFF(void)
{
        WriteCmd(0X8D);//ÉèÖõçºÉ±Ã
        WriteCmd(0X10);//¹Ø±ÕµçºÉ±Ã
        WriteCmd(0XAE);//OLEDÐÝÃß
}

void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
        unsigned char c = 0,i = 0,j = 0;
        switch(TextSize)
        {
                case 1:
                {
                        while(ch != '\0')
                        {
                                c = ch - 32;
                                if(x &gt; 126)
                                {
                                        x = 0;
                                        y++;
                                }
                                OLED_SetPos(x,y);
                                for(i=0;i&lt;6;i++)
                                        WriteDat(F6x8);
                                x += 6;
                                j++;
                        }
                }break;
                case 2:
                {
                        while(ch != '\0')
                        {
                                c = ch - 32;
                                if(x &gt; 120)
                                {
                                        x = 0;
                                        y++;
                                }
                                OLED_SetPos(x,y);
                                for(i=0;i&lt;8;i++)
                                        WriteDat(F8X16);
                                OLED_SetPos(x,y+1);
                                for(i=0;i&lt;8;i++)
                                        WriteDat(F8X16);
                                x += 8;
                                j++;
                        }
                }break;
        }
}

void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
        unsigned char wm=0;
        unsigned intadder=32*N;
        OLED_SetPos(x , y);
        for(wm = 0;wm &lt; 16;wm++)
        {
                WriteDat(F16x16);
                adder += 1;
        }
        OLED_SetPos(x,y + 1);
        for(wm = 0;wm &lt; 16;wm++)
        {
                WriteDat(F16x16);
                adder += 1;
        }
}

void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
        unsigned int j=0;
        unsigned char x,y;

if(y1%8==0)
                y = y1/8;
else
                y = y1/8 + 1;
        for(y=y0;y&lt;y1;y++)
        {
                OLED_SetPos(x0,y);
    for(x=x0;x&lt;x1;x++)
                {
                        WriteDat(BMP);
                }
        }
}
</code></pre>

<p>&nbsp;</p>

<p><span style="font-size:16px;">2.4、oled.h</span></p>

<pre>
<code>#ifndef __OLED_I2C_H
#define        __OLED_I2C_H

#define OLED_ADDRESS        0x3c //ͨ¹ýµ÷Õû0Rµç×è,ÆÁ¿ÉÒÔ0x78ºÍ0x7AÁ½¸öµØÖ· -- ĬÈÏ0x78

void OLED_Init(void);
void OLED_SetPos(unsigned char x, unsigned char y);
void OLED_Fill(unsigned char fill_Data);
void OLED_CLS(void);
void OLED_ON(void);
void OLED_OFF(void);
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize);
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N);
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);

#endif
</code></pre>

<p>&nbsp;</p>

<p><span style="font-size:16px;">2.5、main.c</span></p>

<pre>
<code>#include "ti_msp_dl_config.h"
#include "led/led.h"
#include "systick/systick.h"
#include "uart/uart.h"
#include "key/key.h"
#include "i2c/i2c.h"
#include "i2c/I2C_communication.h"
#include "oled/oled.h"

int main(void)
{
        uint8_t dd=0;
        uint8_t tx_buf;
        SYSCFG_DL_init();
        init_systick();
        init_led();
        init_uart(115200);
        init_i2c();
        key_init();
       
        DL_SYSCTL_disableSleepOnExit();
        printf("mspm0l1306 board test! \r\n");
       
        OLED_Init();
        OLED_Fill(0x00);
        OLED_ShowStr(0,0,"MSPM0L1306",2);
        OLED_ShowStr(0,2,"I2C OLED",2);       
       
        while (1)
        {
                //key_test();
                led2_g_tog();
                SysTick_Delay_ms(20);
        }
}
</code></pre>

<p>&nbsp;</p>

<p><strong><span style="font-size: 16px;">三、运行结果</span></strong></p>

<p>&nbsp;</p>

<p></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

lugl4313820 发表于 2023-11-2 21:38

6666,i2c的硬件驱动的精华就在于这几个I2C_WriteByte之间,其的者是相同的。

TL-LED 发表于 2023-11-2 22:31

lugl4313820 发表于 2023-11-2 21:38
6666,i2c的硬件驱动的精华就在于这几个I2C_WriteByte之间,其的者是相同的。

<p>这个板卡的i2c调试用了不少时间,库函数开始不熟悉。</p>

lugl4313820 发表于 2023-11-3 08:02

TL-LED 发表于 2023-11-2 22:31
这个板卡的i2c调试用了不少时间,库函数开始不熟悉。

<p>辛苦辛苦呀,大佬的文章写得非常不错,花费不少心思吧。</p>

秦天qintian0303 发表于 2023-11-6 11:03

<p>主要是IIC的速度达到不了要求,对于屏幕控制有点慢&nbsp;</p>

TL-LED 发表于 2023-11-6 15:35

秦天qintian0303 发表于 2023-11-6 11:03
主要是IIC的速度达到不了要求,对于屏幕控制有点慢&nbsp;

<p>400K的速率,屏幕小的话还可以吧</p>

秦天qintian0303 发表于 2023-11-6 16:50

TL-LED 发表于 2023-11-6 15:35
400K的速率,屏幕小的话还可以吧

<p>分辨率小点可以,我用SPI驱动屏,240*240分辨率,16M 得速度也不是很快</p>
页: [1]
查看完整版本: 【MSPM0L1306 LaunchPad】i2c驱动OLED显示