OLED屏点亮花费了一段时间,问题出现在 MCUXpresso Config 动态生成的pin_mux 只包含了引脚的分配,但是并没有对引脚进行初始化,这是一直连接不通的原因
另外OLED 虽然写明支持I2C SPI,但是使用硬件接口并不顺序,这方面需要后面来解决,现在用的的软件模拟3线SPI进行驱动
关键代码 如下:
- #include "board.h"
- #include "pin_mux.h"
- #include "fsl_common.h"
- #include "fsl_iocon.h"
- #include
- /*----------------------------------------------*
- * 外部变量说明 *
- *----------------------------------------------*/
- /*----------------------------------------------*
- * 外部函数原型说明 *
- *----------------------------------------------*/
- /*----------------------------------------------*
- * 内部函数原型说明 *
- *----------------------------------------------*/
- /*----------------------------------------------*
- * 全局变量 *
- *----------------------------------------------*/
- /*----------------------------------------------*
- * 模块级变量 *
- *----------------------------------------------*/
- /*----------------------------------------------*
- * 常量定义 *
- *----------------------------------------------*/
- /*----------------------------------------------*
- * 宏定义 *
- *----------------------------------------------*/
- #include "Delay_Log.h"
- #define DispDly_uS(x) S_Log_Delay(x)
-
-
-
-
- #define OLED_MODE_SPI3 1 /* 定义此行表示OLED模块硬件是SPI-3接口模式;不定义则认为是8位并口模式 */
- #define OLED_MODE_SPI4 2 /* 使OLED模块硬件是SPI-4接口模式*/
- #define OLED_MODE_FSMS 3 /*FSMC 8位并口模式*/
- #define OLED_MODE_I2C 4 /* I2C模式 */
- #define OLED_MODE_SET OLED_MODE_SPI3
- #if (OLED_MODE_SET == OLED_MODE_SPI3 )
- /*
- [OLED模块排针] [开发板TFT接口(STM32口线)]
- VCC ----------- 3.3V
- GND ----------- GND
- CS ----------- TP_NCS (PA4) //(PG11)
- RST ----------- NRESET (也可以不连接)
- D0/SCK ----------- TP_SCK (PA5)
- D1/SDIN ----------- TP_MOSI (PA7)
- */
- //#define SSD_CS_RCCAPB RCC_APB2Periph_GPIOB
- //#define SSD_CS_PORT GPIOB
- //#define SSD_CS_GPIO GPIO_Pin_14
- //
- //#define SSD_SDIN_RCCAPB RCC_APB2Periph_GPIOB
- //#define SSD_SDIN_PORT GPIOB
- //#define SSD_SDIN_GPIO GPIO_Pin_15
- //
- //#define SSD_SCK_RCCAPB RCC_APB2Periph_GPIOB
- //#define SSD_SCK_PORT GPIOB
- //#define SSD_SCK_GPIO GPIO_Pin_13
- //#define SSD_CS_1() GPIO_SetBits(SSD_CS_PORT, SSD_CS_GPIO) //GPIOB->BSRR = GPIO_Pin_1 //
- //#define SSD_CS_0() GPIO_ResetBits(SSD_CS_PORT, SSD_CS_GPIO) //GPIOB->BRR = GPIO_Pin_1 //
- //
- //#define SSD_SDIN_1() GPIO_SetBits(SSD_SDIN_PORT, SSD_SDIN_GPIO) //GPIOA->BSRR = GPIO_Pin_7 //
- //#define SSD_SDIN_0() GPIO_ResetBits(SSD_SDIN_PORT, SSD_SDIN_GPIO) //GPIOA->BRR = GPIO_Pin_7 //
- //
- //#define SSD_SCK_1() GPIO_SetBits(SSD_SCK_PORT, SSD_SCK_GPIO) //GPIOA->BSRR = GPIO_Pin_5 //
- //#define SSD_SCK_0() GPIO_ResetBits(SSD_SCK_PORT, SSD_SCK_GPIO) //GPIOA->BRR = GPIO_Pin_5 //
- #define SSD_CS_INIT() GPIO_PinInit(GPIO, 0, 15,&(gpio_pin_config_t){kGPIO_DigitalOutput,1})
- #define SSD_CS_1() GPIO_WritePinOutput(GPIO,0, 15, 1)
- #define SSD_CS_0() GPIO_WritePinOutput(GPIO,0, 15, 0)
- #define SSD_SDIN_INIT() GPIO_PinInit(GPIO, 1, 4,&(gpio_pin_config_t){kGPIO_DigitalOutput,1})
- #define SSD_SDIN_1() GPIO_WritePinOutput(GPIO,1, 4, 1)
- #define SSD_SDIN_0() GPIO_WritePinOutput(GPIO,1, 4, 0)
- #define SSD_SCK_INIT() GPIO_PinInit(GPIO, 1, 5,&(gpio_pin_config_t){kGPIO_DigitalOutput,1})
- #define SSD_SCK_1() GPIO_WritePinOutput(GPIO,1, 5, 1)
- #define SSD_SCK_0() GPIO_WritePinOutput(GPIO,1, 5, 0)
- #elif(OLED_MODE_SET == OLED_MODE_SPI4 )
- #elif(OLED_MODE_SET == OLED_MODE_FSMS )
- /* 定义LCD驱动器的访问地址
- TFT接口中的RS引脚连接FSMC_A0引脚,由于是16bit模式,RS对应A1地址线,因此
- OLED_RAM的地址是+2
- */
- #define OLED_BASE ((uint32)(0x60000000 | 0x0C000000))
- #define OLED_CMD *(__IO uint16_t *)(OLED_BASE)
- #define OLED_DATA *(__IO uint16_t *)(OLED_BASE + 2)
- /*
- [OLED模块排针] [开发板TFT接口(STM32口线)]
- VCC ----------- 3.3V
- GND ----------- GND
- CS ----------- NCS
- RST ----------- NRESET (也可以不连接)
- D/C ----------- RS (FSMC_A0)
- WE ----------- NWE (FSMC_NWE)
- OE ----------- NOE (FSMC_NOE)
- D0/SCK ----------- DB0 (FSMC_D0)
- D1/SDIN ----------- DB1 (FSMC_D1)
- D2 ----------- DB2 (FSMC_D2)
- D3 ----------- DB3 (FSMC_D3)
- D4 ----------- DB4 (FSMC_D4)
- D5 ----------- DB5 (FSMC_D5)
- D6 ----------- DB6 (FSMC_D6)
- D7 ----------- DB7 (FSMC_D7)
- */
- #elif(OLED_MODE_SET == OLED_MODE_I2C )
- #else
- #error "OLED_MODE_SET error define'd in "
- #endif
- /******************************************************************************
- 资料信息
- *******************************************************************************/
- /*
- ------------------------------------------------------------------
- | PA4-SPI1-NSS : SPI_CS# 3CS# |
- | PA5-SPI1-SCK : SPI_SCLK 8D0 |
- | PA6-SPI1-MISO(DO) : 无 |
- | PA7-SPI1-MOSI(DIO) : SPI_SDIN 9D1 |
- | (可以不连接)PA6 : SPI_D/C# 5D/C# |
- | (可以不连接) : SPI_RES# 5RES# |
- | STM32的SPI可以工作在全双工,单向发送,单向接收模式,可以使用DMA方式操作
- */
- /******************************************************************************
- 内部私有函数,移植时关意
- *******************************************************************************/
- /******************************************************************************
- 内部函数 for os 的操作
- *******************************************************************************/
- /*
- *********************************************************************************************************
- * VARIABLES
- *********************************************************************************************************
- */
- //#include "BSP_OS.h"
- //static OS_EVENT *OledDispSem; /* Semaphore used to access display functions */
- /*
- *********************************************************************************************************
- * INITIALIZE RTOS SERVICES
- *
- * Description : This function creates a semaphore to ensure exclusive access to the LCD module and thus
- * provide thread safe access to the display.
- *
- * Arguments : none
- *
- * Returns : none
- *********************************************************************************************************
- */
- void OledDispInitOS (void)
- {
- #if 0
- #if OS_EVENT_NAME_EN > 0
- INT8U err;
- #endif
- OledDispSem = OSSemCreate(1); /* Create display access semaphore */
- #if OS_EVENT_NAME_EN > 0
- OSEventNameSet(OledDispSem, (INT8U *)"Qt/OLED Lock", &err);
- #endif
- #endif
- }
- /*
- *********************************************************************************************************
- * EXCLUSIVE ACCESS FUNCTIONS TO THE DISPLAY
- *
- * Description : These functions are used to gain and release exclusive access to the LCD display.
- *
- * Arguments : none
- *
- * Returns : none
- *********************************************************************************************************
- */
- void OledDispLock (void)
- {
- #if 0
- INT8U err;
- OSSemPend(OledDispSem, 0, &err); /* Obtain exclusive access to the display */
- #endif
- }
- void OledDispUnlock (void)
- {
- #if 0
- OSSemPost(OledDispSem); /* Release access to display */
- #endif
- }
- /******************************************************************************
- 外部公用函数
- *******************************************************************************/
- /*
- *********************************************************************************************************
- * DispInitPort()
- *
- * Description : Initialize the I/O ports used by the display driver.
- *
- * Arguments : none.
- *
- * Returns : none.
- *
- * Caller(s) : DispInit().
- *
- * Notes : none.
- *********************************************************************************************************
- */
- void OLEDInitPort (void)
- {
-
- #if 0
- GPIO_InitTypeDef GPIO_InitStructure;
-
- /* 使能 时钟 */
- RCC_APB2PeriphClockCmd(SSD_CS_RCCAPB | SSD_SDIN_RCCAPB | SSD_SCK_RCCAPB, ENABLE);
- /* 设置 SCK 为推挽输出 */
- GPIO_InitStructure.GPIO_Pin = SSD_SCK_GPIO;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(SSD_SCK_PORT, &GPIO_InitStructure);
-
- /* 设置 SDIN 为推挽输出 */
- GPIO_InitStructure.GPIO_Pin = SSD_SDIN_GPIO;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(SSD_SDIN_PORT, &GPIO_InitStructure);
-
- /* 设置 CS 为推挽输出 */
- GPIO_InitStructure.GPIO_Pin = SSD_CS_GPIO;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init(SSD_CS_PORT, &GPIO_InitStructure);
- #endif
-
- SSD_CS_INIT();
- SSD_SDIN_INIT();
- SSD_SCK_INIT();
-
- /* 设置 CS 为高 复位 */
- SSD_CS_1();
- SSD_SCK_1();
- SSD_SDIN_1();
- }
- /*
- *********************************************************************************************************
- * 函 数 名: OLED_WriteCmd
- * 功能说明: 向SSD1306发送一字节命令
- * 形 参:命令字
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void OLED_WriteCmd(uint8_t _ucCmd)
- {
- uint8_t i;
- SSD_CS_0();
- SSD_SCK_0();
- SSD_SDIN_0(); /* 0 表示后面传送的是命令 1表示后面传送的数据 */
- SSD_SCK_1();
- for (i = 0; i < 8; i++)
- {
- if (_ucCmd & 0x80)
- {
- SSD_SDIN_1();
- }
- else
- {
- SSD_SDIN_0();
- }
- SSD_SCK_0();
- _ucCmd <<= 1;
- SSD_SCK_1();
- }
- SSD_CS_1();
- }
- /*
- *********************************************************************************************************
- * 函 数 名: OLED_WriteData
- * 功能说明: 向SSD1306发送一字节数据
- * 形 参:命令字
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void OLED_WriteData(uint8_t _ucData)
- {
- uint8_t i;
- SSD_CS_0();
- SSD_SCK_0();
- SSD_SDIN_1(); /* 0 表示后面传送的是命令 1表示后面传送的数据 */
- SSD_SCK_1();
- for (i = 0; i < 8; i++)
- {
- if (_ucData & 0x80)
- {
- SSD_SDIN_1();
- }
- else
- {
- SSD_SDIN_0();
- }
- SSD_SCK_0();
- _ucData <<= 1;
- SSD_SCK_1();
- }
- SSD_CS_1();
- }
- /*
- *********************************************************************************************************
- * 函 数 名: OLED_InitHard
- * 功能说明: 初始化OLED屏
- * 形 参:无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void OLED_Init(void)
- {
- OLEDInitPort();
-
- OledDispInitOS();
-
- /* 上电延迟 */
- DispDly_uS(5000);
-
- OledDispLock();
-
- #if 1
- /* 模块厂家提供初始化代码 */
- OLED_WriteCmd(0xAE); /* 关闭OLED面板显示(休眠) */
- OLED_WriteCmd(0x00); /* 设置列地址低4bit */
- OLED_WriteCmd(0x10); /* 设置列地址高4bit */
- OLED_WriteCmd(0x40); /* 设置起始行地址(低5bit 0-63), 硬件相关*/
- OLED_WriteCmd(0x81); /* 设置对比度命令(双字节命令),第1个字节是命令,第2个字节是对比度参数0-255 */
- OLED_WriteCmd(0xCF); /* 设置对比度参数 */
- OLED_WriteCmd(0xA1); /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
- OLED_WriteCmd(0xA6); /* A6 : 设置正常显示模式; A7 : 设置为反显模式 */
- OLED_WriteCmd(0xA8); /* 设置COM路数 */
- OLED_WriteCmd(0x3F); /* 1 ->(63+1)路 */
- OLED_WriteCmd(0xD3); /* 设置显示偏移(双字节命令)*/
- OLED_WriteCmd(0x00); /* 无偏移 */
- OLED_WriteCmd(0xD5); /* 设置显示时钟分频系数/振荡频率 */
- OLED_WriteCmd(0x80); /* 设置分频系数,高4bit是分频系数,低4bit是振荡频率 */
- OLED_WriteCmd(0xD9); /* 设置预充电周期 */
- OLED_WriteCmd(0xF1); /* [3:0],PHASE 1; [7:4],PHASE 2; */
- OLED_WriteCmd(0xDA); /* 设置COM脚硬件接线方式 */
- OLED_WriteCmd(0x12);
- OLED_WriteCmd(0xDB); /* 设置 vcomh 电压倍率 */
- OLED_WriteCmd(0x40); /* [6:4] 000 = 0.65 x VCC; 0.77 x VCC (RESET); 0.83 x VCC */
- OLED_WriteCmd(0x8D); /* 设置充电泵(和下个命令结合使用) */
- OLED_WriteCmd(0x14); /* 0x14 使能充电泵, 0x10 是关闭 */
- OLED_WriteCmd(0xAF); /* 打开OLED面板 */
- #else
- /* 模块厂家提供初始化代码 悠景科技 UG-2864HSWEG01 Evaluation Kit User Guide.pdf */
- OLED_WriteCmd(0xAE); /* 关闭OLED面板显示(休眠) */
- OLED_WriteCmd(0x00); /* 设置列地址低4bit */
- OLED_WriteCmd(0x10); /* 设置列地址高4bit */
-
- /*1、Set Mux ration*/
- OLED_WriteCmd(0xA8); /* 设置COM路数 */
- OLED_WriteCmd(0x3F); /* 1 ->(63+1)路 */
- /*2、Set Display offset*/
- OLED_WriteCmd(0xD3); /* 设置显示偏移(双字节命令)*/
- OLED_WriteCmd(0x00); /* 无偏移 */
- /*3、Set Display Start line 与Display offset 组合可以做来偏移效果,修改硬件上安装不足*/
- OLED_WriteCmd(0x40); /*0x40~0x7f 设置起始行地址(低5bit 0-63), 硬件相关 */
- /*0x40 设置起始行地址0: RAM row 0 ->COM0
- 0X41 设置起始行地址1: RAM row 1 ->COM0 */
- /*4、Set Segment re-map SEG列-128 COM行-64*/
- OLED_WriteCmd(0xA1); /* 默认0xA0 :列地址0映射到SEG0; 0xA1 :列地址127映射到SEG0 */
- /*5、Set COM Output Scan Direction */
- OLED_WriteCmd(0xC0); /*0xc0 由下向上; 0XC8 由上向下 不设置或者默认值影响不大*/
- /*6、Set COM Pins hardware configuration*/
- OLED_WriteCmd(0xDA); /* 设置COM脚硬件接线方式 */
- OLED_WriteCmd(0x12);
- /*7、Set Contrast Control*/
- OLED_WriteCmd(0x81); /* 设置对比度命令(双字节命令),第1个字节是命令,第2个字节是对比度参数0-255 */
- OLED_WriteCmd(0xCF); /* 设置对比度参数 0x00 ~0xff*/
- /*8、Set Normal Display*/
- OLED_WriteCmd(0xA6); /* A6 : 设置正常允灸J? A7 : 设置为反显模式 */
- /*9、Set Osc Frequency*/
- OLED_WriteCmd(0xD5); /* 设置显示时钟分频系数/振荡频率 */
- OLED_WriteCmd(0x80); /* 设置分频系数,高4bit是分频系数,低4bit是振荡频率 */
- OLED_WriteCmd(0xD9); /* 设置预充电周期 */
- OLED_WriteCmd(0xF1); /* [3:0],PHASE 1; [7:4],PHASE 2; */
- OLED_WriteCmd(0xDB); /* 设置 vcomh 电压倍率 */
- OLED_WriteCmd(0x40); /* [6:4] 000 = 0.65 x VCC; [6:4] 010 =0.77 x VCC (RESET); [6:4] 01 =0.83 x VCC */
- /*9、Enalbe charge pump regulator*/
- OLED_WriteCmd(0x8D); /* 设置充电泵(和下个命令结合使用) */
- OLED_WriteCmd(0x14); /* 0x14 使能充电泵, 0x10 是关闭 */
- /*10、Display On */
- OLED_WriteCmd(0xAF); /* 打开OLED面板 */
- #endif
- OledDispUnlock();
- }
- /*
- *********************************************************************************************************
- * 函 数 名: OLED_DispOn
- * 功能说明: 打开显示
- * 形 参:无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void OLED_DispOn(void)
- {
- OledDispLock();
-
- OLED_WriteCmd(0x8D); /* 设置充电泵(和下个命令结合使用) */
- OLED_WriteCmd(0x14); /* 0x14 使能充电泵, 0x10 是关闭 */
- OLED_WriteCmd(0xAF); /* 打开OLED面板 */
-
- OledDispUnlock();
- }
- /*
- *********************************************************************************************************
- * 函 数 名: OLED_DispOff
- * 功能说明: 关闭显示
- * 形 参:无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void OLED_DispOff(void)
- {
- OledDispLock();
- OLED_WriteCmd(0x8D); /* 设置充电泵(和下个命令结合使用)*/
- OLED_WriteCmd(0x10); /* 0x14 使能充电泵,0x10 是关闭 */
- OLED_WriteCmd(0xAE); /* 打开OLED面板 */
-
- OledDispUnlock();
- }
- /*--------- void OLED_DispContrast(unsigned char val) -----
- 形式参数:val对比度参数 0X00 ~ 0XFF
- 返回值:void
- 函数描述:设置对比度
- ------------------------------------------*/
- void OLED_DispContrast(uint8_t val)
- {
- OledDispLock();
-
- OLED_WriteCmd(0x81); /* 设置对比度命令(双字节命令),第1个字节是命令,第2个字节是对比度参数0-255 */
- OLED_WriteCmd(val); /* 设置对比度参数 0x00 ~0xff*/
-
- OledDispUnlock();
- }
- void OledDispClrScr (void)
- {
- }
- /*
- *********************************************************************************************************
- * 函 数 名: OLED_PutPixel
- * 功能说明: 画1个像素
- * 形 参:
- * tsX,tsY : 像素坐标
- * tcColor :像素颜色
- * 返 回 值: 无
- *********************************************************************************************************
- */
- #if 0
- void OLED_PutPixel(uint16_t tsX, uint16_t tsY, uint8_t tcColor)
- {
- uint8_t ucValue;
- uint8_t ucPageAddr;
- uint8_t ucColAddr;
-
- #ifdef TRUN_180_EN
- ucPageAddr = tsY / 8;
- ucColAddr = 127 - tsX;
- #else
- ucPageAddr = 7 - tsY / 8;
- ucColAddr = tsX;
- #endif
-
- OledDispLock();
-
- OLED_WriteCmd (0xB0 + ucPageAddr); /* 设置页地址(0~7) */
- OLED_WriteCmd (0x00 + (ucColAddr & 0x0F)); /* 设置列地址的低地址 */
- OLED_WriteCmd (0x10 + ((ucColAddr >> 4) & 0x0F)); /* 设置列地址的高地址 */
- OLED_WriteData(ucValue);
-
- OledDispUnlock();
- }
- #else
- /* 使用缓冲区的概念,减少对硬件的频繁操作*/
- /* 12864 OLED的显存镜像,占用1K字节. 共8行,每行128像素 */
- static uint8_t stcGRAM[8][128];
- void OLED_PutPixel(uint16_t tsX, uint16_t tsY, uint8_t tcColor)
- {
- uint8_t ucValue;
- uint8_t ucPageAddr;
- uint8_t ucColAddr;
- uint8_t mflag=false; //如果数据相同不用更新数据
- #ifdef TRUN_180_EN
- const uint8_t aOrTab[8] = {0x01, 0x02, 0x04, 0x08,0x10,0x20,0x40,0x80};
- const uint8_t aAndTab[8] = {0xFE, 0xFD, 0xFB, 0xF7,0xEF,0xDF,0xBF,0x7F};
- ucPageAddr = tsY / 8;
- ucColAddr = 127 - tsX;
- #else
- const uint8_t aOrTab[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
- const uint8_t aAndTab[8] = {0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE};
- ucPageAddr = 7 - tsY / 8;
- ucColAddr = tsX;
- #endif
- OledDispLock();
- ucValue = stcGRAM[ucPageAddr][ucColAddr];
- if (tcColor == 0)
- {
-
- if( (ucValue&aAndTab[tsY % 8]) != ucValue ) //数据发生变化
- {
- mflag=true;
- ucValue &= aAndTab[tsY % 8];
- }
-
- }
- else
- {
- if( (ucValue|aOrTab[tsY % 8]) != ucValue ) //数据发生变化
- {
- mflag=true;
- ucValue |= aOrTab[tsY % 8];
- }
- }
-
- if( mflag==true )
- {
- stcGRAM[ucPageAddr][ucColAddr] = ucValue;
- //if (stcUpdateEn == 1)
- {
-
- OLED_WriteCmd (0xB0 + ucPageAddr); /* 设置页地址(0~7) */
- OLED_WriteCmd (0x00 + (ucColAddr & 0x0F)); /* 设置列地址的低地址 */
- OLED_WriteCmd (0x10 + ((ucColAddr >> 4) & 0x0F)); /* 设置列地址的高地址 */
- OLED_WriteData(ucValue);
-
- }
- }
-
- OledDispUnlock();
- }
- #endif
- /*
- *********************************************************************************************************
- * 函 数 名: OLED_ClrScr
- * 功能说明: 清屏
- * 形 参:tcMode : 0 表示全黑; 0xFF表示全亮
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void OLED_ClrScr(uint8_t tcMode)
- {
- uint8_t i,j;
-
- OledDispLock();
- for (i = 0 ; i < 8; i++)
- {
- OLED_WriteCmd (0xB0 + i); /* 设置页地址(0~7) */
- OLED_WriteCmd (0x00); /* 设置列地址的低地址 */
- OLED_WriteCmd (0x10); /* 设置列地址的高地址 */
- for (j = 0 ; j < 128; j++)
- {
- stcGRAM[i][j] = tcMode;
- OLED_WriteData(stcGRAM[i][j]);
- }
- }
- OledDispUnlock();
- }
复制代码
|