加入交流群  

扫一扫,添加管理员微信
备注:参考设计,即可被拉入群
和也在搞设计小伙伴们碰一碰

收藏 

评论 

蓝猫淘气 发布

【立创开发板】立创开发板NES游戏机

 
设计简介

一、项目简介

  基于立创梁山派GD32F4高性能开发板制作自己的游戏机,这游戏机移植NES模拟器,目前一般NES游戏都可以玩,目前有上百款游戏下载。在这项目当中,我们可以很好地学习LCD屏的移植,SD卡的文件系统的使用,简单UI界面制作,音乐输出的功能,等等。在这项目当中我们可以回忆童年时光。

二、板载功能资源

(图1 PCB正面)

(图2 PCB反面)

 

三、重点学习内容:

1、文件系统,Fats读写操作(SD卡与Flash 的文件系统)。

2EXMCLCD驱动(8080LCD接口)

3、移植NES的显示240*240改成480*480

4、液晶屏触摸控制及玩游戏

5DAC音乐输出

6、文字库使

7SDRAM的内存管理

8Bmp图片文件读取存储显示

 

四、电路原理图介绍:

 

1、电源管理部分:

3TYPE-C 充电接口,二极管可以防反灌输入。

(图4)电源管理模块

 图4是充电与升压管理部分。U10为充电IC,充电电流最大1AU9为升压ICME2159)一款比较优秀的锂电池升压IC2.5V-4.2V宽电压转换效率可以达到90%

如下图5(官方手册测试参数):

(图5)ME2159 性能图

图4中CHG1CHG2为充电IC的正在充电、充电完成状态信号。R27电阻是插入充电电源后停止升压,程序要拨充电电源后延时重启否则白屏。右侧R16R19电池电压采样电流,计算电池电压公式:

faValue = adcValue*(3.368/4096)*fadcoffset;

        A.    favalue:电池电压

        B.     adcValueADC读取的值

        C.     fadcoffset:矫正值

 

2、语音放大电路:

(图6)DAC输出信号放大电路

图6中改变R10与R8 的比例可以实现改变音频放大的倍数,可以让喇叭声音变大。

 

3、游戏控制遥杆

(图7)兼容两款遥杆的电路

实物展示:

图8

型号:RKJXV1220001

立创商城购买:RKJXV1220001_(ALPSALPINE(阿尔卑斯阿尔派))RKJXV1220001中文资料_价格_PDF手册-立创电子商城 (szlcsc.com)

图9

型号:无

淘宝购买:https://item.taobao.com/item.htm?spm=a1z09.2.0.0.38cf2e8dqWGxGP&id=642782754225&_u=jak0o1p43a3

 

五、系统框架

图10、系统图

 

1、显示屏选用:购买的立创`梁山派-屏幕扩展板 10件套(详情请点击以下)

立创`梁山派-屏幕扩展板_(立创开发板)立创`梁山派-屏幕扩展板中文资料_价格_PDF手册-立创电子商城 (szlcsc.com)

2、梁山派开发板:立创·梁山派 GD32F470ZGT6开发板 五件套(详情请点击以下)

立创·梁山派 GD32F470ZGT6开发板_(立创开发板)立创·梁山派 GD32F470ZGT6开发板中文资料_价格_PDF手册-立创电子商城 (szlcsc.com)

3、组合后(接好后):

这是完整接好的样子。

这是开机后的样子。

这个是游戏界面

 

 

 

 

六、程序重点描述

 

1、EXMC驱动TFT-LCD与SDRAM共用:

          初次调试,EXMC的LCD驱动时发现SDRAM存储异常,运行游戏失败,LCD显示正常,如果屏蔽LCD驱动,SDRAM就正常运行游戏,因为游戏文件要加载到SDRAM上运行。问题就是SDRAM和TFT-LCD共用就程序异常跑飞,最终解决问题,优化了SDRAM的时序延时。

代码如下:

ErrStatus exmc_synchronous_dynamic_ram_init(uint32_t sdram_device)
{
    exmc_sdram_parameter_struct        sdram_init_struct;
    exmc_sdram_timing_parameter_struct  sdram_timing_init_struct;
    exmc_sdram_command_parameter_struct     sdram_command_init_struct;

    uint32_t command_content = 0, bank_select;
    uint32_t timeout = SDRAM_TIMEOUT;

    /* enable EXMC clock*/
    rcu_periph_clock_enable(RCU_EXMC);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_GPIOD);
    rcu_periph_clock_enable(RCU_GPIOE);
    rcu_periph_clock_enable(RCU_GPIOF);
    rcu_periph_clock_enable(RCU_GPIOG);
    rcu_periph_clock_enable(RCU_GPIOH);

    /* common GPIO configuration */
    /* SDNWE(PC0),SDNE0(PC2),SDCKE0(PC3) pin configuration */ 
    gpio_af_set(GPIOC, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3);

    /* D2(PD0),D3(PD1),D13(PD8),D14(PD9),D15(PD10),D0(PD14),D1(PD15) pin configuration */
    gpio_af_set(GPIOD, GPIO_AF_12, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_8 | GPIO_PIN_9 |
                                   GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_8 | GPIO_PIN_9 |
                                                         GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_8 | GPIO_PIN_9 |
                                                                     GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);

    /* NBL0(PE0),NBL1(PE1),D4(PE7),D5(PE8),D6(PE9),D7(PE10),D8(PE11),D9(PE12),D10(PE13),D11(PE14),D12(PE15) pin configuration */
    gpio_af_set(GPIOE, GPIO_AF_12, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_7  | GPIO_PIN_8 |
                                   GPIO_PIN_9  | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
                                   GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_7  | GPIO_PIN_8 |
                                                         GPIO_PIN_9  | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
                                                         GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_7  | GPIO_PIN_8 |
                                                                     GPIO_PIN_9  | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
                                                                     GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);

    /* A0(PF0),A1(PF1),A2(PF2),A3(PF3),A4(PF4),A5(PF5),NRAS(PF11),A6(PF12),A7(PF13),A8(PF14),A9(PF15) pin configuration */
    gpio_af_set(GPIOF, GPIO_AF_12, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_2  | GPIO_PIN_3  |
                                   GPIO_PIN_4  | GPIO_PIN_5  | GPIO_PIN_11 | GPIO_PIN_12 |
                                   GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
    gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_2  | GPIO_PIN_3  |
                                                         GPIO_PIN_4  | GPIO_PIN_5  | GPIO_PIN_11 | GPIO_PIN_12 |
                                                         GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
    gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_2  | GPIO_PIN_3  |
                                                                     GPIO_PIN_4  | GPIO_PIN_5  | GPIO_PIN_11 | GPIO_PIN_12 |
                                                                     GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);

    /* A10(PG0),A11(PG1),A12(PG2),A14(PG4),A15(PG5),SDCLK(PG8),NCAS(PG15) pin configuration */
    gpio_af_set(GPIOG, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | 
                                   GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
    gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | 
                                                         GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
    gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | 
                                                                     GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);

    /* specify which SDRAM to read and write */
    if(EXMC_SDRAM_DEVICE0 == sdram_device){
        bank_select = EXMC_SDRAM_DEVICE0_SELECT;
    }else{
        bank_select = EXMC_SDRAM_DEVICE1_SELECT;
    }

    /* EXMC SDRAM device initialization sequence --------------------------------*/
    /* Step 1 : configure SDRAM timing registers --------------------------------*/
    /* LMRD: 2 clock cycles */
    sdram_timing_init_struct.load_mode_register_delay = 2;
    /* XSRD: min = 75ns */
    sdram_timing_init_struct.exit_selfrefresh_delay = 9;  
    /* RASD: min=44ns , max=120k (ns) */
    sdram_timing_init_struct.row_address_select_delay = 5;  
    /* ARFD: min=66ns */
    sdram_timing_init_struct.auto_refresh_delay = 8;  
    /* WRD:  min=1 Clock cycles +7.5ns */
    sdram_timing_init_struct.write_recovery_delay = 3;
    /* RPD:  min=20ns */
    sdram_timing_init_struct.row_precharge_delay = 3; 
    /* RCD:  min=20ns */
    sdram_timing_init_struct.row_to_column_delay = 3; 

    /* step 2 : configure SDRAM control registers ---------------------------------*/
    sdram_init_struct.sdram_device = sdram_device;
    sdram_init_struct.column_address_width = EXMC_SDRAM_COW_ADDRESS_9;
    sdram_init_struct.row_address_width = EXMC_SDRAM_ROW_ADDRESS_13;
    sdram_init_struct.data_width = EXMC_SDRAM_DATABUS_WIDTH_16B;
    sdram_init_struct.internal_bank_number = EXMC_SDRAM_4_INTER_BANK;
    sdram_init_struct.cas_latency = EXMC_CAS_LATENCY_3_SDCLK;  
    sdram_init_struct.write_protection = DISABLE;
    sdram_init_struct.sdclock_config = EXMC_SDCLK_PERIODS_2_HCLK;  
    sdram_init_struct.brust_read_switch = ENABLE;
    sdram_init_struct.pipeline_read_delay = EXMC_PIPELINE_DELAY_2_HCLK;
    sdram_init_struct.timing  = &sdram_timing_init_struct;
    /* EXMC SDRAM bank initialization */
    exmc_sdram_init(&sdram_init_struct);

    /* step 3 : configure CKE high command---------------------------------------*/
    sdram_command_init_struct.command = EXMC_SDRAM_CLOCK_ENABLE;
    sdram_command_init_struct.bank_select = bank_select;
    sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_2_SDCLK;
    sdram_command_init_struct.mode_register_content = 0;
    /* wait until the SDRAM controller is ready */ 
    while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)){
        timeout--;
    }
    if(0 == timeout){
        return ERROR;
    }    
    /* send the command */
    exmc_sdram_command_config(&sdram_command_init_struct);

    /* step 4 : insert 10ms delay----------------------------------------------*/
    delay_1ms(10);

    /* step 5 : configure precharge all command----------------------------------*/
    sdram_command_init_struct.command = EXMC_SDRAM_PRECHARGE_ALL;
    sdram_command_init_struct.bank_select = bank_select;
    sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;
    sdram_command_init_struct.mode_register_content = 0;
    /* wait until the SDRAM controller is ready */
    timeout = SDRAM_TIMEOUT; 
    while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)){
        timeout--;
    }
    if(0 == timeout){
        return ERROR;
    }    
    /* send the command */
    exmc_sdram_command_config(&sdram_command_init_struct);

    /* step 6 : configure Auto-Refresh command-----------------------------------*/
    sdram_command_init_struct.command = EXMC_SDRAM_AUTO_REFRESH;
    sdram_command_init_struct.bank_select = bank_select;
    sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_8_SDCLK;
    sdram_command_init_struct.mode_register_content = 0;
    /* wait until the SDRAM controller is ready */ 
    timeout = SDRAM_TIMEOUT; 
    while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)){
        timeout--;
    }
    if(0 == timeout){
        return ERROR;
    }    
    /* send the command */
    exmc_sdram_command_config(&sdram_command_init_struct);

    /* step 7 : configure load mode register command-----------------------------*/
    /* program mode register */
    command_content = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1        |
                                SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
                                SDRAM_MODEREG_CAS_LATENCY_3           |
                                SDRAM_MODEREG_OPERATING_MODE_STANDARD |
                                SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;

    sdram_command_init_struct.command = EXMC_SDRAM_LOAD_MODE_REGISTER;
    sdram_command_init_struct.bank_select = bank_select;
    sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_2_SDCLK;
    sdram_command_init_struct.mode_register_content = command_content;

    /* wait until the SDRAM controller is ready */ 
    timeout = SDRAM_TIMEOUT; 
    while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)){
        timeout--;
    }
    if(0 == timeout){
        return ERROR;
    }    
    /* send the command */
    exmc_sdram_command_config(&sdram_command_init_struct);

    /* step 8 : set the auto-refresh rate counter--------------------------------*/
    /* 64ms, 8192-cycle refresh, 64ms/8192=7.81us */
    /* SDCLK_Freq = SYS_Freq/2 */
    /* (7.81 us * SDCLK_Freq) - 20 */
    exmc_sdram_refresh_count_set(761); 

    /* wait until the SDRAM controller is ready */ 
    timeout = SDRAM_TIMEOUT; 
    while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)){
        timeout--;
    }
    if(0 == timeout){
        return ERROR;
    }
    return SUCCESS;    
}

   修改完代码后,程序正常运行游戏。

 

2、TFT-LCD显示图片修改:

 

原代码是这样的:

void LCD_ShowPicture1(uint16_t x,uint16_t y,uint16_t length,uint16_t width,const uint8_t *pic)
{
uint16_t i,j;
uint32_t k=0;
LCD_Address_Set(x,y,x+length-1,y+width-1);
    
    LCD_DC_Set();//写数据
    LCD_CS_Clr();
for(i=0;i<length;i++)
{
for(j=0;j<width;j++)
{
            while(RESET == spi_i2s_flag_get(SPI4, SPI_FLAG_TBE));
            spi_i2s_data_transmit(SPI4, *pic++);
            while(RESET == spi_i2s_flag_get(SPI4, SPI_FLAG_TBE));
            spi_i2s_data_transmit(SPI4, *pic++);
}
}
    while(RESET == spi_i2s_flag_get(SPI4, SPI_FLAG_RBNE));
    while(SET == spi_i2s_flag_get(SPI4, SPI_STAT_TRANS));
    LCD_CS_Set();
    
    while(spi_i2s_flag_get(SPI4, SPI_FLAG_RBNE)) i=spi_i2s_data_receive(SPI4);
}

 

源代码显示图片是直接使用SPI对显示屏写入数据,没有直接调用LCD驱动的方法,若是不留意就程序一开机会挂在这里

8080显示驱动 修改为:

void LCD_ShowPicture1(uint16_t x,uint16_t y,uint16_t length,uint16_t width,const uint8_t *pic)
{
    uint16_t i,j;
    uint32_t k=0;
 
     uint16_t pdat;
 
LCD_Address_Set(x,y,x+length-1,y+width-1);
    
for(i=0;i<length;i++)
{
for(j=0;j<width;j++)
{
pdat = pic[k*2];
pdat = pdat<<8|pic[k*2+1];
 
LCD_WR_DATAs(pdat);
 
k++;
 
}
      }   
}

 

    字库更新:(需要的字库文件:UNIGBK.BIN,GBK12.BIN,GBK16.BIN,GBK24.BIN)我在正点原子找了字库文件,拿来用,发现出现以下的显示问题:

      

找到问题所在:text.c   --->   Show_Font 函数如下:

//************************************************************************

void Show_Font(u16 x,u16 y,u8 *font,uint16_t fc,uint16_t bc,u8 size,u8 mode)
{
u8 temp,t,t1;
u16 y0=y;
u8 dzk[72];   
u8 csize=(size/8+((size%8)?1:0))*(size);//得到字体一个字符对应点阵集所占的字节数 
if(size!=12&&size!=16&&size!=24)return;//不支持的size
Get_HzMat(font,dzk,size);//得到相应大小的点阵数据 
for(t=0;t<csize;t++)
{      
temp=dzk[t];      //得到点阵数据                          
for(t1=0;t1<8;t1++)
{
          if(temp&0x80) LCD_DrawPoint(x,y,fc);
            else if(mode==0) LCD_DrawPoint(x,y,bc);
temp<<=1;
y++;
if((y-y0)==size)
{
y=y0;
x++;
break;
}
}   
}  
}

//***************************************************************************

把函数里的X和Y改改就可以了,改过如下:

//**********************************************************

 
void Show_Font(u16 x,u16 y,u8 *font,uint16_t fc,uint16_t bc,u8 size,u8 mode)
{
u8 temp,t,t1;
// u16 y0=y;
u16 x0=x;
u8 dzk[72];   
u8 csize=(size/8+((size%8)?1:0))*(size);//得到字体一个字符对应点阵集所占的字节数 
if(size!=12&&size!=16&&size!=24)return;//不支持的size
Get_HzMat(font,dzk,size);//得到相应大小的点阵数据 
for(t=0;t<csize;t++)
{      
temp=dzk[t];//得到点阵数据                          
for(t1=0;t1<8;t1++)
{
            if(temp&0x80) LCD_DrawPoint(x,y,fc);
            else if(mode==0) LCD_DrawPoint(x,y,bc);
temp<<=1;
x++;
if((x-x0)==size)
{
  x=x0;
  y++;
  break;
}
}   
     }
}
 
 
 

//**************************************************  

其次游戏的显示驱动:240*240分辨率改成480*480分辨率,不需要增加显存的情况下:

nes_ppu.c  ---->    void scanline_draw(int  LineNo)函数

 

//***********************************************************************************

extern uint8_t nes_xoff; //显示在x轴方向的偏移量(实际显示宽度=256-2*nes_xoff)

void scanline_draw(int LineNo)

{

 

uint16 i; 

uint16_t sx,ex;

do_scanline_and_draw(ppu->dummy_buffer);

 

  #if 0

  sx=nes_xoff+8;

  ex=256+8-nes_xoff;

 

  //printf("LineNo:%d sx:%d ex:%d ",LineNo,sx,ex);

  LCD_Address_Set(LineNo,sx,LineNo,ex);//设置显示范围 横着屏幕

  for(i=sx;i<ex;i++){

    //LCD_DrawPoint(LineNo,i,NES_Palette[ppu->dummy_buffer[i]]);

    //printf("i:%d color:%d ",i,NES_Palette[ppu->dummy_buffer[i]]);

    LCD_WR_DATA(NES_Palette[ppu->dummy_buffer[i]]);

  }

  #else

  sx = 17;

  ex = 240+17;

    

    

    LCD_Address_Set(0,(LineNo*2)+40,480,(LineNo*2)+40);//设置显示范围 横着屏显示

   

for(i=sx;i<ex;i++){

 

LCD_WR_DATAs(NES_Palette[ppu->dummy_buffer[i]]);

LCD_WR_DATAs(NES_Palette[ppu->dummy_buffer[i]]);

 

}

 

 

LCD_Address_Set(0,(LineNo*2+1)+40,480,(LineNo*2+1)+40);//设置显示范围 横着屏显示

    

//LCD_DC_Set();//写数据

    // LCD_CS_Clr();

    

 

for(i=sx;i<ex;i++){

 

LCD_WR_DATAs(NES_Palette[ppu->dummy_buffer[i]]);

LCD_WR_DATAs(NES_Palette[ppu->dummy_buffer[i]]);

 

}

}

 

函数里红色部分:大概原理就是x坐标数据写入两次,Y坐标的一行写两行,等于 一个点放大加1倍,240*240的内存显示放大成 480*480,节省RAM显存。

 

游戏显示部分好了.

 

 

 

3、讲讲Bmp文件显示:

bmp的函数代码复制于教材的源码改的,

重要文件:file_opera.c      bmp_opera.c

修改了屏蔽了这两个程序里大多数的LCD驱动代码,只留下bmp文件处理解析的内容。

fatsbmp文件,bmp文件信息的主意格式结构体(bmp_opera.h):

//BMP文件主要信息结构体

typedef struct

{

//1. 文件信息头

uint16  tbfType;//开头2个字节,文件类型,必须是0x4D42

uint32  tbfSize;//文件大小,字节为单位

uint32_tbfOffset;    //数据起始偏移地址,单位:字节  

 

//2. 位图信息头

uint32  tbiSize;//信息头字节数,一般就是40

uint32 tbiWidth;//BMP图宽度,像素

uint32 tbiHeight;//BMP图高度,像素

uint16 tbiBitCount;//每个像素的比特数

} BMPFileInfoDef;

 

bmp文件在SD卡内存储,文件信息数据排列顺序就根据这个结构图排列:

//调用以下函数读取BMP文件信息, 文件信息保存到指针BmpFileInfo指向的变量

uint8_t ReadBmpFileInfo(uint8_t *Filename, BMPFileInfoDef *BmpFileInfo)

{

FIL  file;

FRESULT res=f_open(&file, (char *)Filename, FA_READ);         //fats 读取bmp文件信息

if(res != FR_OK)

{

f_close(&file);

return 0;     //失败返回0

}

 

ReadBmpHeader(&file, BmpFileInfo);//读取文件头信息

 

f_close(&file);        //成功后关闭清除file句柄

return 1;   //成功返回1

}

 

然后,可以用void    ShowBmpFileInfo(const BMPFileInfoDef *BmpFileInfo)  把bmp文件的信息通过printf打印出来

 

再然后,bmp文件图片数据显示到LCD上,图片是24位RGB888, 一个像素3个字节,排列顺序BGR,
BMP图片从下开始往上逐行存储, 在电脑上对图片进行了上下翻转,所以直接顺序读取,

需要转换为RGB565表示的像素点数据,才能画到LCD上

 

 

边读边显示的函数:

void DrawBmp(const uint16_t  PosX, const uint16_t PosY,

FIL *file, BMPFileInfoDef *fileInfo)

 

在LCD上绘制整个BMP图片,返回值为0表示绘图成功
uint8_t    DrawBmpFile(const uint16_t  PosX, const uint16_t PosY, uint8_t *Filename)

 

以上是Bmp图片直接显示LCD屏上,后面我自己改了个直接读数据保存在SDRAM里的

uint32_t BmpRead(uint16_t *buf ,FIL *file, BMPFileInfoDef *fileInfo)


//读BMP图片把数据写buffer里,返回值为0表示绘图成功
uint8_t    ReadBmpFile(uint16_t *buf ,  uint8_t *Filename,BMPFileInfoDef    *fileInfo)

 

后面调用程序,使用方法(NES_GUI.c里):

先分配图片内存:

 

然后读取bmp数据到RAM里:

这些函数把图片显示内容,读到RAM里,再显示

LCD_DrawBmp 因为LCD屏定了是自上往下显示的,bmp文件的内容是自下往上的,所以改了这个函数。

 

 

 

 

参考设计图片
×

!注意:请使用浏览器自带下载,迅雷等下载软件可能无法下载到有效资源。

 
相关器件
器件 类型 描述 数据手册
M24C02-WMN6TP EEPROM存储器 存储器接口类型:I2C 存储器容量:2Kb (256 x 8) 工作电压:2.5V ~ 5.5V 存储器类型:Non-Volatile 2-Kbit(256 x 8bit),I2C接口,工作电压:2.5V to 5.5V 点击下载
C0603X5R106M160NT 贴片电容 精度:±20% 容值:10uF 额定电压:16V 温漂系数(介质材料):X5R X5R 点击下载
CC0603KRX7R9BB104 贴片电容 精度:±10% 容值:100nF 额定电压:50V 温漂系数(介质材料):X7R 材质:X7R 点击下载
8002A 音频功率放大器 点击下载
CR0603FA1002G 贴片电阻 阻值(欧姆):10K 精度:±1% 功率:1/10W 温度系数:±100ppm/°C 1/10W 点击下载
FN18X224K160PSG 贴片电容 精度:±10% 容值:220nF 额定电压:16V 温漂系数(介质材料):X7R 材质:X7R 点击下载
AC0603DR-0768KL 贴片电阻 阻值(欧姆):68K 精度:±0.5% 功率:1/10W 温度系数:±100ppm/°C 点击下载
CC0603KRX5R8BB105 贴片电容 精度:±10% 容值:1uF 额定电压:25V 温漂系数(介质材料):X5R 材质:X5R 点击下载
HPCR0603F22K0K9 高功率贴片电阻 功率:200mW 阻值(欧姆):22K 精度:±1% 0.2W,额定功率是普通贴片电阻的一倍 点击下载
S8050 三极管 晶体管类型:NPN 集电极电流Ic:500mA 集射极击穿电压Vce:25V 额定功率:225mW NPN 点击下载
CR0603F1K00P05Z 贴片电阻 点击下载
CR0603JA0103G 贴片电阻 阻值(欧姆):10K 精度:±5% 功率:1/10W 温度系数:±200ppm/°C 点击下载
1N4148W 开关二极管 反向恢复时间(trr):8ns 直流反向耐压(Vr):75V 平均整流电流(Io):150mA 正向压降(Vf):1V @ 10mA 点击下载
0603WAF0000T5E 贴片电阻 阻值(欧姆):0 精度:±1% 功率:1/10W 温度系数:- 点击下载
0603WAF1002T5E 贴片电阻 阻值(欧姆):10K 精度:±1% 功率:1/10W 温度系数:±100ppm/°C 点击下载
CL10A106KP8NNNC 贴片电容 精度:±10% 容值:10uF 额定电压:10V 温漂系数(介质材料):X5R 材质:X5R 点击下载
ME2159AM6G DC-DC芯片 可输出电流:2A 开关工作频率:1MHz 输出类型:Adjustable 输出电压的路数:1 功能类型:Step-Up 输出配置:Positive 升压IC 锂电池升压 点击下载
SS24A 肖特基二极管 直流反向耐压(Vr):40V 平均整流电流(Io):2A 正向压降(Vf):500mV @ 2A 点击下载
TMPC0502HP-4R7MG-D 功率电感 精度:±20% 电感值:4.7uH 直流电阻(内阻):103mΩ 额定电流:2.8A 点击下载
AC0805FR-0788K7L 贴片电阻 阻值(欧姆):88.7K 精度:±1% 功率:1/8W 温度系数:±100ppm/°C 点击下载
AC0805FR-0712KL 贴片电阻 阻值(欧姆):12K 精度:±1% 功率:1/8W 温度系数:±100ppm/°C 点击下载
CL21A106KAYNNNE 贴片电容 精度:±10% 容值:10uF 额定电压:25V 温漂系数(介质材料):X5R 材质:X5R 每盘2000个 7''REEL 点击下载
CL21B104KCFNNNE 贴片电容 精度:±10% 容值:100nF 额定电压:100V 温漂系数(介质材料):X7R 材质:X7R 点击下载
MMBT3904 三极管 额定功率:350mW 集电极电流Ic:200mA 集射极击穿电压Vce:40V 晶体管类型:NPN 点击下载
0603WAF1001T5E 贴片电阻 阻值(欧姆):1K 精度:±1% 功率:1/10W 温度系数:±100ppm/°C 点击下载
RVT100UF10V67RV0036 贴片型铝电解电容 点击下载
KH-TYPE-C-16P USB连接器 点击下载
2.54-1*2P母 排针排母 针脚数:2 连接器类型:排母 排数:1 触头类型:母形插口 间距:0.100"(2.54mm) 点击下载
RKJXV1220001 多功能开关 电位器式多功能操作装置 点击下载
SKPMAPE010 轻触开关 电路结构:SPST-NO 触点额定电流:50mA @ 16VDC 按钮头类型:Round Button 按钮作用方向:Top Actuated 点击下载
A2501WR-S-4P 线对板/线对线连接器 针脚数:4 连接器类型:针座 系列:XH 间距:0.098"(2.50mm) 触头类型:公形引脚 XH连接器 XH2.5 点击下载
群聊设计,与管理员及时沟通

欢迎加入EEWorld参考设计群,也许能碰到搞同一个设计的小伙伴,群聊设计经验和难点。 入群方式:微信搜索“helloeeworld”或者扫描二维码,备注:参考设计,即可被拉入群。 另外,如您在下载此设计遇到问题,也可以微信添加“helloeeworld”及时沟通。

 
查找数据手册?

EEWorld Datasheet 技术支持

论坛推荐 更多
更新时间2024-11-09 20:18:42

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版 版权声明

EEWORLD参考设计中心

站点相关: TI培训 德州仪器(TI)官方视频课程培训

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved