kit7828 发表于 2022-3-10 13:54

【GD32L233C-START 评测】-七、SPI方式驱动1.5寸OLED屏

<p>GD用了一段时间了,感觉各方面比较接近STM32了,打算移植一些STM32的例程评测下。</p>

<p>手头有块老王家的1.5寸OLED屏,在STM32环境下用微雪的驱动能显示图片了,于是改下成GD32的</p>

<p>花了些时间把STM32HAL的改成GD32的库函数版本,不知道GD是否也有HAL库?</p>

<p>连接方式用的是</p>

<p>&nbsp; OLED这边用的7根线连接的</p>

<p>核心的SPI代码跟上个例程是一样的</p>

<pre>
<code>void SpiInit(void)
{
        spi_parameter_struct spi_init_struct;
        //rcu_periph_clock_enable(RCU_SPI_PORT);
        rcu_periph_clock_enable(RCU_SPI1);
       
//        gpio_mode_set(RST_522_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, RST_522_PIN );
//gpio_output_options_set(RST_522_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, RST_522_PIN);
//       
//        /* SPI1 GPIO configuration: NSS/PB12 */
//        gpio_mode_set(SPI_CS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SPI_CS_PIN );
//        gpio_output_options_set(SPI_CS_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI_CS_PIN);

        /* SPI1 GPIO configuration: SCK/PB13, MISO/PB14, MOSI/PB15 */
        gpio_af_set(GPIOB, GPIO_AF_6, GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
        gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
        gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);

        /* deinitilize SPI and the parameters */
        spi_i2s_deinit(SPI1);
        spi_struct_para_init(&amp;spi_init_struct);

        /* SPI1 parameter configuration */
        spi_init_struct.trans_mode         = SPI_TRANSMODE_FULLDUPLEX;
        spi_init_struct.device_mode          = SPI_MASTER;
        spi_init_struct.frame_size         = SPI_FRAMESIZE_8BIT;
        spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
        spi_init_struct.nss                  = SPI_NSS_SOFT;
        spi_init_struct.prescale             = SPI_PSC_8;
        spi_init_struct.endian               = SPI_ENDIAN_MSB;
        spi_init(SPI1, &amp;spi_init_struct);
       
        spi_crc_polynomial_set(SPI1, 7);

        spi_enable(SPI1);
}

uint8_tSPIWriteByte(uint8_t Byte)
{
        while(RESET == spi_i2s_flag_get(SPI1, SPI_FLAG_TBE)) {};   //等待发送区空       
    spi_i2s_data_transmit(SPI1, Byte);                         //发送一个byte
        while(RESET == spi_i2s_flag_get(SPI1, SPI_FLAG_RBNE)) {};//等待接收完一个byte

        return spi_i2s_data_receive(SPI1);                                                                        //返回收到的数据
}</code></pre>

<p>OLED驱动用的是微雪的例程</p>

<pre>
<code>static void OLED_Reset(void)
{
    OLED_RST_1;
    Driver_Delay_ms(100);
    OLED_RST_0;
    Driver_Delay_ms(100);
    OLED_RST_1;
    Driver_Delay_ms(100);
}

/*******************************************************************************
function:
            Write register address and data
*******************************************************************************/
static void OLED_WriteReg(uint8_t Reg)
{
//#if USE_SPI_4W
        OLED_DC_0;
    OLED_CS_0;
    //SPI4W_Write_Byte(Reg);
                SPIWriteByte(Reg);
    OLED_CS_1;
//#elif USE_IIC
//    I2C_Write_Byte(Reg,IIC_CMD);
//#endif
}

static void OLED_WriteData(uint8_t Data)
{   
//#if USE_SPI_4W
    OLED_DC_1;
    OLED_CS_0;
    //SPI4W_Write_Byte(Data);
                SPIWriteByte(Data);
    OLED_CS_1;
//#elif USE_IIC
//    I2C_Write_Byte(Data,IIC_RAM);
//#endif
}

/*******************************************************************************
function:
      Common register initialization
*******************************************************************************/
static void OLED_InitReg(void)
{
    OLED_WriteReg(0xae);//--turn off oled panel

    OLED_WriteReg(0x15);    //   set column address
    OLED_WriteReg(0x00);    //start column   0
    OLED_WriteReg(0x7f);    //end column   127

    OLED_WriteReg(0x75);    //   set row address
    OLED_WriteReg(0x00);    //start row   0
    OLED_WriteReg(0x7f);    //end row   127

    OLED_WriteReg(0x81);// set contrast control
    OLED_WriteReg(0x80);

    OLED_WriteReg(0xa0);    // gment remap
    OLED_WriteReg(0x51);   //51

    OLED_WriteReg(0xa1);// start line
    OLED_WriteReg(0x00);

    OLED_WriteReg(0xa2);// display offset
    OLED_WriteReg(0x00);

    OLED_WriteReg(0xa4);    // rmal display
    OLED_WriteReg(0xa8);    // set multiplex ratio
    OLED_WriteReg(0x7f);

    OLED_WriteReg(0xb1);// set phase leghth
    OLED_WriteReg(0xf1);

    OLED_WriteReg(0xb3);// set dclk
    OLED_WriteReg(0x00);//80Hz:0xc1 90Hz:0xe1   100Hz:0x00   110Hz:0x30 120Hz:0x50   130Hz:0x70   01

    OLED_WriteReg(0xab);//
    OLED_WriteReg(0x01);//

    OLED_WriteReg(0xb6);// set phase leghth
    OLED_WriteReg(0x0f);

    OLED_WriteReg(0xbe);
    OLED_WriteReg(0x0f);

    OLED_WriteReg(0xbc);
    OLED_WriteReg(0x08);

    OLED_WriteReg(0xd5);
    OLED_WriteReg(0x62);

    OLED_WriteReg(0xfd);
    OLED_WriteReg(0x12);

}

/********************************************************************************
function:
            initialization
********************************************************************************/
void OLED_1in5_Init(void)
{
    //Hardware reset
    OLED_Reset();

    //Set the initialization register
    OLED_InitReg();
    Driver_Delay_ms(200);

    //Turn on the OLED display
    OLED_WriteReg(0xAF);
}

/********************************************************************************
function:   Set the display Window(Xstart, Ystart, Xend, Yend)
parameter:
      xStart :   X direction Start coordinates
      Ystart :   Y direction Start coordinates
      Xend   :   X direction end coordinates
      Yend   :   Y direction end coordinates
********************************************************************************/
static void OLED_SetWindow(UBYTE Xstart, UBYTE Ystart, UBYTE Xend, UBYTE Yend)
{
    if((Xstart &gt; OLED_1in5_WIDTH) || (Ystart &gt; OLED_1in5_HEIGHT) ||
       (Xend &gt; OLED_1in5_WIDTH) || (Yend &gt; OLED_1in5_HEIGHT))
      return;

    OLED_WriteReg(0x15);
    OLED_WriteReg(Xstart/2);
    OLED_WriteReg(Xend/2 - 1);

    OLED_WriteReg(0x75);
    OLED_WriteReg(Ystart);
    OLED_WriteReg(Yend - 1);
}

/********************************************************************************
function:
            Clear screen
********************************************************************************/
void OLED_1in5_Clear(void)
{
    UWORD i;
    OLED_SetWindow(0, 0, 128, 128);
    for(i=0; i&lt;OLED_1in5_WIDTH*OLED_1in5_HEIGHT/2; i++){
      OLED_WriteData(0x00);
    }
}

/********************************************************************************
function:   Update all memory to OLED
********************************************************************************/
void OLED_1in5_Display(const UBYTE *Image)
{
    UWORD i, j, temp;
    OLED_SetWindow(0, 0, 128, 128);
    for(i=0; i&lt;OLED_1in5_HEIGHT; i++)
      for(j=0; j&lt;OLED_1in5_WIDTH/2; j++)
      {
            temp = Image;
            OLED_WriteData(temp);
      }
}</code></pre>

<p>本以为会一切顺利的,STM32下很正常能运行,但是GD这边,居然卡在了malloc上面</p>

<pre>
<code>UBYTE *BlackImage;
        UWORD Imagesize = ((OLED_1in5_WIDTH%2==0)? (OLED_1in5_WIDTH/2): (OLED_1in5_WIDTH/2+1)) * OLED_1in5_HEIGHT;
        if((BlackImage = (UBYTE *)malloc(Imagesize)) == NULL) {
                        printf("Failed to apply for black memory...\r\n");
                        return -1;
        }</code></pre>

<p>查了很多资料,也增大了堆和栈的空间,始终在malloc这里出错。目前还是没有解决这个malloc的问题。</p>

<p>动态分配失败,就改成了静态分配,先创建了数组</p>

<pre>
<code>UBYTE OLEDImage;

int OLED_1in5_test(void)
{
        printf("1.5inch OLED test demo\n");
//        if(System_Init() != 0) {
//                return -1;
//        }
          
        printf("OLED Init...\r\n");
        OLED_1in5_Init();
        Driver_Delay_ms(500);
        OLED_1in5_Clear();
       
        // 0.Create a new image cache
        UBYTE *BlackImage;
//        UWORD Imagesize = ((OLED_1in5_WIDTH%2==0)? (OLED_1in5_WIDTH/2): (OLED_1in5_WIDTH/2+1)) * OLED_1in5_HEIGHT;
//        if((BlackImage = (UBYTE *)malloc(Imagesize)) == NULL) {
//                        printf("Failed to apply for black memory...\r\n");
//                        return -1;
//        }
        BlackImage = OLEDImage;
        printf("Paint_NewImage\r\n");
        Paint_NewImage(BlackImage, OLED_1in5_WIDTH, OLED_1in5_HEIGHT, 270, BLACK);       
        Paint_SetScale(16);
        printf("Drawing\r\n");
        //1.Select Image
        Paint_SelectImage(BlackImage);
        Driver_Delay_ms(500);
        Paint_Clear(BLACK);
        while(1) {
               
                // 2.Drawing on the image               
                printf("Drawing:page 1\r\n");
                Paint_DrawPoint(20, 10, WHITE, DOT_PIXEL_1X1, DOT_STYLE_DFT);
                Paint_DrawPoint(30, 10, WHITE, DOT_PIXEL_2X2, DOT_STYLE_DFT);
                Paint_DrawPoint(40, 10, WHITE, DOT_PIXEL_3X3, DOT_STYLE_DFT);
                Paint_DrawLine(10, 10, 10, 20, WHITE, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
                Paint_DrawLine(20, 20, 20, 30, WHITE, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
                Paint_DrawLine(30, 30, 30, 40, WHITE, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);
                Paint_DrawLine(40, 40, 40, 50, WHITE, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);
                Paint_DrawCircle(60, 30, 15, WHITE, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
                Paint_DrawCircle(100, 40, 20, WHITE, DOT_PIXEL_1X1, DRAW_FILL_FULL);                       
                Paint_DrawRectangle(50, 30, 60, 40, WHITE, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
                Paint_DrawRectangle(90, 30, 110, 50, BLACK, DOT_PIXEL_1X1, DRAW_FILL_FULL);               
                // 3.Show image on page1
                OLED_1in5_Display(BlackImage);
                Driver_Delay_ms(2000);                       
                Paint_Clear(BLACK);

                // Drawing on the image
                printf("Drawing:page 2\r\n");
                for(UBYTE i=0; i&lt;16; i++){
                        Paint_DrawRectangle(0, 8*i, 127, 8*(i+1), i, DOT_PIXEL_1X1, DRAW_FILL_FULL);
                }                       
                // Show image on page2
                OLED_1in5_Display(BlackImage);
                Driver_Delay_ms(2000);       
                Paint_Clear(BLACK);       
               
                // Drawing on the image
                printf("Drawing:page 3\r\n");                       
                Paint_DrawString_EN(10, 0, "waveshare", &amp;Font16, 0x1, 0xb);
                Paint_DrawString_EN(10, 17, "hello world", &amp;Font8, 0x2, 0xc);
                Paint_DrawNum(10, 30, 123.456789, &amp;Font8, 4, 0x3, 0xd);
                Paint_DrawNum(10, 43, 987654, &amp;Font12, 5, 0x4, 0xe);
                // Show image on page2
                OLED_1in5_Display(BlackImage);
                Driver_Delay_ms(2000);       
                Paint_Clear(BLACK);               
               
                // Drawing on the image
                printf("Drawing:page 4\r\n");
                Paint_DrawString_CN(10, 0,"你好Abc", &amp;Font12CN, WHITE, WHITE);
                Paint_DrawString_CN(0, 20, "微雪电子", &amp;Font24CN, WHITE, WHITE);
                // Show image on page3
                OLED_1in5_Display(BlackImage);
                Driver_Delay_ms(2000);               
                Paint_Clear(BLACK);               

                // show the array image
                printf("Drawing:page 5\r\n");
                OLED_1in5_Display(gImage_1in5);
                Driver_Delay_ms(2000);               
                Paint_Clear(BLACK);       

        }
}</code></pre>

<p>整个例程就能正常运行了。</p>

<p>&nbsp;项目整体文件</p>

<p><a href="javascript:;" id="attachname592248" isimage="0" onclick="insertAttachTag('592248');doane(event);" title="15-SPI-OLED.rar
上传日期: 2022-3-10 13:54
文件大小: 436.59 KB">15-SPI-OLED.rar</a>attach://592248.rar</p>

soso 发表于 2022-3-11 09:33

<p>总体移植感受怎么样?</p>

kit7828 发表于 2022-3-11 13:00

soso 发表于 2022-3-11 09:33
总体移植感受怎么样?

<p>整体还不错,基本都能成功</p>

soso 发表于 2022-3-11 14:00

kit7828 发表于 2022-3-11 13:00
整体还不错,基本都能成功

<p>赞:)</p>

wangerxian 发表于 2022-3-11 15:35

<p>移植的还是挺成功的!没太多坑。</p>

freebsder 发表于 2022-3-11 23:01

<p>32家族好繁盛。</p>

kit7828 发表于 2022-3-17 16:22

wangerxian 发表于 2022-3-11 15:35
移植的还是挺成功的!没太多坑。

<p>是的,SPI还算顺利</p>

<p>&nbsp;</p>
页: [1]
查看完整版本: 【GD32L233C-START 评测】-七、SPI方式驱动1.5寸OLED屏