【GD32L233C-START 评测】-七、SPI方式驱动1.5寸OLED屏
[复制链接]
GD用了一段时间了,感觉各方面比较接近STM32了,打算移植一些STM32的例程评测下。
手头有块老王家的1.5寸OLED屏,在STM32环境下用微雪的驱动能显示图片了,于是改下成GD32的
花了些时间把STM32HAL的改成GD32的库函数版本,不知道GD是否也有HAL库?
连接方式用的是
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);
}
}
整个例程就能正常运行了。
项目整体文件
15-SPI-OLED.rarhttps://bbs.eeworld.com.cn/forum.php?mod=attachment&aid=NTkyMjQ4fDJhYjkwN2ZiZWQ1ODg5ZWM1ZWZkM2YxYTYwYjQ0OTg4fDE3MzIxOTI4MTI%3D&request=yes&_f=.rar
|