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

kit7828   2022-3-10 13:54 楼主

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

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

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

连接方式用的是

image.png   OLED这边用的7根线连接的

核心的SPI代码跟上个例程是一样的

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(&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, &spi_init_struct);
	
	spi_crc_polynomial_set(SPI1, 7);

	spi_enable(SPI1);
}

uint8_t  SPIWriteByte(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);									//返回收到的数据
}

OLED驱动用的是微雪的例程

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 > OLED_1in5_WIDTH) || (Ystart > OLED_1in5_HEIGHT) ||
       (Xend > OLED_1in5_WIDTH) || (Yend > 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<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<OLED_1in5_HEIGHT; i++)
        for(j=0; j<OLED_1in5_WIDTH/2; j++)
        {
            temp = Image[j + i*64];
            OLED_WriteData(temp);
        }
}

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

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;
	}

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

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

UBYTE OLEDImage[OLED_1in5_WIDTH/2 * OLED_1in5_HEIGHT];

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<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", &Font16, 0x1, 0xb);
		Paint_DrawString_EN(10, 17, "hello world", &Font8, 0x2, 0xc);
		Paint_DrawNum(10, 30, 123.456789, &Font8, 4, 0x3, 0xd);
		Paint_DrawNum(10, 43, 987654, &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", &Font12CN, WHITE, WHITE);
		Paint_DrawString_CN(0, 20, "微雪电子", &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);	

	}
}

整个例程就能正常运行了。

OLED-SPI0.gif  项目整体文件

15-SPI-OLED.rarhttps://m.eeworld.com.cn/bbs/forum.php?mod=attachment&aid=NTkyMjQ4fDFhMDFiNGZiNTAzODBlMmZhYTk2NTgwMTdjNTc0YjYyfDE3MzE2NDU3NjM%3D&request=yes&_f=.rar

回复评论 (6)

总体移植感受怎么样?

加油!在电子行业默默贡献自己的力量!:)
点赞  2022-3-11 09:33
引用: soso 发表于 2022-3-11 09:33 总体移植感受怎么样?

整体还不错,基本都能成功

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

赞:)

加油!在电子行业默默贡献自己的力量!:)
点赞  2022-3-11 14:00

移植的还是挺成功的!没太多坑。

点赞  2022-3-11 15:35

32家族好繁盛。

默认摸鱼,再摸鱼。2022、9、28
点赞  2022-3-11 23:01
引用: wangerxian 发表于 2022-3-11 15:35 移植的还是挺成功的!没太多坑。

是的,SPI还算顺利

 

点赞  2022-3-17 16:22
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复