需求:从flash芯片中读取图片数据到psram,然后发送到显示上,在读取flash和显示之间如果将数据打印出来,图片就能正常显示,否则就是花屏,以下是相关代码:
Code: Select all
STATIC VOID_T display_flash_image(UINT16_T x,UINT16_T y,UINT16_T w,UINT16_T h,UINT32_T addr)
{
UINT32_T image_size;
image_size=w*h*2;
buffer=tkl_system_psram_malloc(image_size);
if(buffer==NULL)
{
TAL_PR_NOTICE("display psram malloc fail!");
return;
}
tal_mutex_lock(gx_dis_mutex);
hly_flash_read(addr,buffer,image_size);
// for(UINT32_T i=0;i<153600;i++)
// {
// TAL_PR_NOTICE("***buufer %06X:%02X",i,*(buffer+i));
// }
screen_draw_image(x,y,w,h,buffer);
tal_mutex_unlock(gx_dis_mutex);
tkl_system_free(buffer);
buffer=NULL;
}
SPI部分使用了DMA,并且移除了官方关于CS引脚的相关代码
Code: Select all
#define SPI_ID TUYA_SPI_NUM_0 // SPI ID
STATIC QUEUE_HANDLE gx_spi_queue_handle; //spi消息队列
/*spi init*/
CONST TUYA_SPI_BASE_CFG_T GX_SPI_CFG = {
.mode = TUYA_SPI_MODE3,
.freq_hz = SPI_FREQ,
.databits = TUYA_SPI_DATA_BIT8,
.bitorder = TUYA_SPI_ORDER_MSB2LSB,
.role = TUYA_SPI_ROLE_MASTER,
.type = TUYA_SPI_SOFT_TYPE,//TUYA_SPI_AUTO_TYPE,//
.spi_dma_flags=0
};
STATIC VOID_T spi_irq_cb(TUYA_SPI_NUM_E port, TUYA_SPI_IRQ_EVT_E event)
{
UINT8_T e;
//TAL_PR_DEBUG("spi irq=%d",(UINT8_T)TUYA_SPI_EVENT_RX_COMPLETE);
if(port==SPI_ID&&event==TUYA_SPI_EVENT_RX_COMPLETE)
{
e=2;
tal_queue_post(gx_spi_queue_handle,&e,100);
}
}
OPERATE_RET hly_spi_init(VOID_T)
{
OPERATE_RET rt = OPRT_OK;
tal_queue_create_init(&gx_spi_queue_handle,sizeof(UINT8_T),1);
tkl_spi_irq_init(SPI_ID,spi_irq_cb);
tkl_spi_irq_enable(SPI_ID);
rt = tkl_spi_init(SPI_ID, &GX_SPI_CFG);
return rt;
}
OPERATE_RET hly_spi_write_byte(UINT8_T data)
{
OPERATE_RET rt;
TUYA_SPI_IRQ_EVT_E tmp;
tal_queue_fetch(gx_spi_queue_handle,&tmp,300);
rt=tkl_spi_send(SPI_ID, &data, 1);
//TAL_PR_DEBUG("spi send:%d rt=%d",data,rt);
return rt;
}
OPERATE_RET hly_spi_write_buffer(UINT8_T* data,UINT32_T len)
{
TUYA_SPI_IRQ_EVT_E tmp;
tal_queue_fetch(gx_spi_queue_handle,&tmp,300);
while(len>0)
{
if(len>=1024)
{
tkl_spi_send(SPI_ID, data, 1024);
len-=1024;
data+=1024;
}
else
{
tkl_spi_send(SPI_ID, data, len);
len-=len;
}
if(tal_queue_fetch(gx_spi_queue_handle,&tmp,300)!=OPRT_OK)
{
return OPRT_COM_ERROR;
}
}
return OPRT_OK;
}
UINT8_T hly_spi_read_btye()
{
UINT8_T data;
tkl_spi_recv(SPI_ID,&data,1);
return data;
}
OPERATE_RET hly_spi_read_buffer(UINT8_T* buffer,UINT32_T len)
{
while(len)
{
if(len>=1024)
{
tkl_spi_recv(SPI_ID,buffer,1024);
len-=1024;
buffer+=1024;
}
else
{
tkl_spi_recv(SPI_ID,buffer,len);
len-=len;
buffer+=len;
}
}
return OPRT_OK;
}
屏幕显示相关函数
Code: Select all
#define SCREEN_CS_PIN TUYA_GPIO_NUM_18 // CS引脚
#define SCREEN_RES_PIN TUYA_GPIO_NUM_47 // RES引脚
#define SCREEN_DC_PIN TUYA_GPIO_NUM_46 // DC引脚
#define SCREEN_BL_PIN TUYA_GPIO_NUM_19 // 背光
#define SCREEN_CS_H() do { \
*((volatile unsigned long *) (SOC_AON_GPIO_REG_BASE+(SCREEN_CS_PIN)*4)) = GPIO_OUTPUT_HIGH; \
} while(0)
#define SCREEN_CS_L() do { \
*((volatile unsigned long *) (SOC_AON_GPIO_REG_BASE+(SCREEN_CS_PIN)*4)) = GPIO_OUTPUT_LOW; \
} while(0)
// #define SCREEN_CS_H do{}while(0)
// #define SCREEN_CS_L do{}while(0)
#define SCREEN_RES_H() do { \
*((volatile unsigned long *) (SOC_AON_GPIO_REG_BASE+(SCREEN_RES_PIN)*4)) = GPIO_OUTPUT_HIGH; \
} while(0)
#define SCREEN_RES_L() do { \
*((volatile unsigned long *) (SOC_AON_GPIO_REG_BASE+(SCREEN_RES_PIN)*4)) = GPIO_OUTPUT_LOW; \
} while(0)
#define SCREEN_DC_H() do { \
*((volatile unsigned long *) (SOC_AON_GPIO_REG_BASE+(SCREEN_DC_PIN)*4)) = GPIO_OUTPUT_HIGH; \
} while(0)
#define SCREEN_DC_L() do { \
*((volatile unsigned long *) (SOC_AON_GPIO_REG_BASE+(SCREEN_DC_PIN)*4)) = GPIO_OUTPUT_LOW; \
} while(0)
#define SCREEN_BL_H() do { \
*((volatile unsigned long *) (SOC_AON_GPIO_REG_BASE+(SCREEN_BL_PIN)*4)) = GPIO_OUTPUT_HIGH; \
} while(0)
#define SCREEN_BL_L() do { \
*((volatile unsigned long *) (SOC_AON_GPIO_REG_BASE+(SCREEN_BL_PIN)*4)) = GPIO_OUTPUT_LOW; \
} while(0)
// #define SCREEN_RAM_SIZE 1024
// UINT16_T gb_screen_rom[SCREEN_RAM_SIZE];
CONST TUYA_GPIO_BASE_CFG_T GX_GPIO_CFG =
{
.mode = TUYA_GPIO_OPENDRAIN_PULLUP,
.direct = TUYA_GPIO_OUTPUT,
.level = TUYA_GPIO_LEVEL_HIGH
};
STATIC VOID_T screen_cmd(UINT8_T cmd)
{
SCREEN_DC_L();
SCREEN_CS_L();
hly_spi_write_byte(cmd);
SCREEN_CS_H();
}
STATIC VOID_T screen_data8(UINT8_T dat)
{
SCREEN_DC_H();
SCREEN_CS_L();
hly_spi_write_byte(dat);
SCREEN_CS_H();
}
STATIC VOID_T screen_data16(UINT16_T dat)
{
SCREEN_DC_H();
SCREEN_CS_L();
hly_spi_write_byte(dat>>8);
hly_spi_write_byte(dat);
SCREEN_CS_H();
}
STATIC VOID screen_set_rectangle(UINT16_T x0, UINT16_T y0, UINT16_T x1, UINT16_T y1)
{
screen_cmd(0x2A);
screen_data16(x0);
screen_data16(x1);
screen_cmd(0x2B);
screen_data16(y0);
screen_data16(y1);
screen_cmd(0x2C);
}
OPERATE_RET screen_init(VOID_T)
{
tkl_gpio_init(SCREEN_CS_PIN, &GX_GPIO_CFG);
tkl_gpio_init(SCREEN_DC_PIN, &GX_GPIO_CFG);
tkl_gpio_init(SCREEN_RES_PIN, &GX_GPIO_CFG);
SCREEN_CS_H();
SCREEN_BL_L();
SCREEN_RES_L();
tal_system_sleep(100);
SCREEN_RES_H();
tal_system_sleep(100); // ms
screen_cmd(0x11);
tal_system_sleep(100); // ms
screen_cmd(0x36);
screen_data8(0x70);
screen_cmd(0x3A);
screen_data8(0x05); // 262Kɫ 06
screen_cmd(0xB2);
screen_data8(0x0C);
screen_data8(0x0C);
screen_data8(0x00);
screen_data8(0x33);
screen_data8(0x33);
screen_cmd(0xB7);
screen_data8(0x75); // VGH=14.97V, VGL=-10.43V
screen_cmd(0xBB); // VCOM
screen_data8(0x21);
screen_cmd(0xC0);
screen_data8(0x2C);
screen_cmd(0xC2);
screen_data8(0x01);
screen_cmd(0xC3); // GVDD
screen_data8(0x13);
screen_cmd(0xC4);
screen_data8(0x20);
screen_cmd(0xC6);
screen_data8(0x0F);
screen_cmd(0xD0);
screen_data8(0xA4);
screen_data8(0xA1);
screen_cmd(0xd6);
screen_data8(0xa1);
screen_cmd(0xE0);
screen_data8(0x70);
screen_data8(0x04);
screen_data8(0x0A);
screen_data8(0x08);
screen_data8(0x07);
screen_data8(0x05);
screen_data8(0x32);
screen_data8(0x32);
screen_data8(0x48);
screen_data8(0x38);
screen_data8(0x15);
screen_data8(0x15);
screen_data8(0x2A);
screen_data8(0x2E);
screen_cmd(0xE1);
screen_data8(0x70);
screen_data8(0x07);
screen_data8(0x0D);
screen_data8(0x09);
screen_data8(0x09);
screen_data8(0x16);
screen_data8(0x30);
screen_data8(0x44);
screen_data8(0x49);
screen_data8(0x39);
screen_data8(0x16);
screen_data8(0x16);
screen_data8(0x2B);
screen_data8(0x2F);
screen_cmd(0x21);
screen_cmd(0x29);
// screen_fill(0,0,320,240,0x0000);
TAL_PR_DEBUG("---------------screen init done----------.");
SCREEN_BL_H();
return 0;
}
OPERATE_RET screen_fill(UINT16_T x,UINT16_T y,UINT16_T w,UINT16_T h,UINT16_T color)
{
UINT32_T i;
UINT32_T count;
count=w*h;
screen_set_rectangle(x,y,x+w-1,y+h-1);
SCREEN_DC_H();
SCREEN_CS_L();
// while(count)
// {
// if(count>SCREEN_RAM_SIZE)
// {
// for(i=0;i<SCREEN_RAM_SIZE;i++)
// {
// gb_screen_rom[i]=color;
// }
// hly_spi_write_buffer(&gb_screen_rom,SCREEN_RAM_SIZE*2);
// count-=SCREEN_RAM_SIZE;
// }
// else
// {
// for(i=0;i<count;i++)
// {
// gb_screen_rom[i]=color;
// }
// hly_spi_write_buffer(&gb_screen_rom,count*2);
// count-=count;
// }
// }
//SCREEN_RAM_SIZE
//count=10;
for(i=0;i<count;i++)
{
hly_spi_write_byte(color>>8);
hly_spi_write_byte(color);
}
SCREEN_CS_H();
}
OPERATE_RET screen_draw_image(UINT16_T x,UINT16_T y,UINT16_T w,UINT16_T h,UINT8_T* image)
{
UINT32_T count;
count=w*h*2;
screen_set_rectangle(x,y,x+w-1,y+h-1);
SCREEN_DC_H();
SCREEN_CS_L();
hly_spi_write_buffer(image,count);
SCREEN_CS_H();
}
FLASH操作相关函数
Code: Select all
#define FLASH_CS_PIN TUYA_GPIO_NUM_15
#define FLASH_CS_H() do { \
*((volatile unsigned long *) (SOC_AON_GPIO_REG_BASE+(FLASH_CS_PIN)*4)) = GPIO_OUTPUT_HIGH; \
} while(0)
#define FLASH_CS_L() do { \
*((volatile unsigned long *) (SOC_AON_GPIO_REG_BASE+(FLASH_CS_PIN)*4)) = GPIO_OUTPUT_LOW; \
} while(0)
CONST TUYA_GPIO_BASE_CFG_T GX_FLASH_GPIO_CFG =
{
.mode = TUYA_GPIO_OPENDRAIN_PULLUP,
.direct = TUYA_GPIO_OUTPUT,
.level = TUYA_GPIO_LEVEL_HIGH
};
OPERATE_RET hly_flash_init()
{
OPERATE_RET rt;
rt=tkl_gpio_init(FLASH_CS_PIN, &GX_FLASH_GPIO_CFG);
FLASH_CS_H() ;
return rt;
}
// 等待25Q64空闲
STATIC OPERATE_RET hly_flash_idle() {
UINT16_T t=0;
unsigned char status;
do {
// t++;
// if (t>1000)
// {
// return -1;
// }
FLASH_CS_L();
hly_spi_write_byte(0x05); // 读状态寄存器命令
status = hly_spi_read_btye();
FLASH_CS_H();
} while (status & 0x01); // 忙标志位
return 0;
}
STATIC OPERATE_RET hly_flash_page_program(UINT32_T addr,UINT8_T* databuffer,UINT32_T len)
{
OPERATE_RET rt;
FLASH_CS_L();
hly_spi_write_byte(0x06); //写使能
FLASH_CS_H();
FLASH_CS_L();
hly_spi_write_byte(0x02); //页编程
hly_spi_write_byte((addr>>16)&0xFF);
hly_spi_write_byte((addr>>8)&0xFF);
hly_spi_write_byte((addr&0xFF));
rt=hly_spi_write_buffer(databuffer,len);
FLASH_CS_H();
if(rt=0)
{
rt=hly_flash_idle();
}
return rt;
}
OPERATE_RET hly_flash_write(UINT32_T addr,UINT8_T* databuffer,UINT32_T len)
{
OPERATE_RET rt;
UINT32_T bytesWritten = 0;
while (len > 0) {
UINT32_T bytesToWrite = (len > 256) ? 256 : len;
rt=hly_flash_page_program(addr + bytesWritten, databuffer + bytesWritten, bytesToWrite);
bytesWritten += bytesToWrite;
len -= bytesToWrite;
}
return rt;
}
OPERATE_RET hly_flash_read(UINT32_T addr,UINT8_T* databuffer,UINT32_T len)
{
OPERATE_RET rt;
FLASH_CS_L();
hly_spi_write_byte(0x0B); //快速读取
hly_spi_write_byte((addr>>16)&0xFF);
hly_spi_write_byte((addr>>8)&0xFF);
hly_spi_write_byte((addr&0xFF));
rt=hly_spi_read_buffer(databuffer,len);
FLASH_CS_H();
return rt;
}
OPERATE_RET hly_flash_full_erase()
{
OPERATE_RET rt;
FLASH_CS_L();
hly_spi_write_byte(0x06); //写使能
FLASH_CS_H();
FLASH_CS_L();
hly_spi_write_byte(0xC7); //全部擦除
FLASH_CS_H();
rt=hly_flash_idle();
return rt;
}