STM32F103 系列芯片读写AT45DB161芯片的程序和写入/读取字库文件的方法

作者:残心秀士

转自:http://www.52rd.com/Blog/Detail_RD.Blog_swordlife_23439.html


在项目中用到2M Byte容量的Flash芯片AT45DB161,用来存放字库文件,这两天在写AT45DB161的读取控制程序,在参考网上的一些控制代码的基础上,编写成功。现总结经验如下:

1. AT45DB161芯片内部有两个page buffer,每一个page buffer默认是528 Byte。而Datasheet上说这个Page buffer的大小可以设定为512Byte;我在实际使用的时候没有修改设定,只是对一个page写入512个Byte而已,剩下的不管;读取的时候,读取528个Byte,只取前面512 Byte,剩下的不理睬。

 

以下是AT45DB161的控制程序代码:

 

__________________________________________________

#define AT45DB_BUFFER_1_WRITE                 0x84 /* 写入第一缓冲区 */
#define AT45DB_BUFFER_2_WRITE                 0x87 /* 写入第二缓冲区 */
#define AT45DB_BUFFER_1_WRITE_FLASH           0x82 /* 写入第一缓冲区 */
#define AT45DB_BUFFER_2_WRITE_FLASH           0x85 /* 写入第二缓冲区 */

#define AT45DB_BUFFER_1_READ                  0xD4 /* 读取第一缓冲区 */
#define AT45DB_BUFFER_2_READ                  0xD6 /* 读取第二缓冲区 */
#define AT45DB_B1_TO_MM_PAGE_PROG_WITH_ERASE  0x83 /* 将第一缓冲区的数据写入主存储器(擦除模式)*/
#define AT45DB_B2_TO_MM_PAGE_PROG_WITH_ERASE  0x86 /* 将第二缓冲区的数据写入主存储器(擦除模式)*/
#define AT45DB_MM_PAGE_TO_B1_XFER             0x53 /* 将主存储器的指定页数据加载到第一缓冲区    */
#define AT45DB_MM_PAGE_TO_B2_XFER             0x55 /* 将主存储器的指定页数据加载到第二缓冲区    */
#define AT45DB_PAGE_ERASE                     0x81 /* 页删除(每页512/528字节) */
#define AT45DB_SECTOR_ERASE                   0x7C /* 扇区擦除(每扇区128K字节)*/
#define AT45DB_READ_STATE_REGISTER            0xD7 /* 读取状态寄存器 */
#define AT45DB_BLACK_ERASE       0x50 /* 块删除(每块4KByte)*/
#define AT45DB_MM_PAGE_READ       0xD2 /* 直接读主存储器的内存页*/

#define AT45DB_16HZ_Block_Number   64  //占用256K字节存储空间,那么要占用256/4=64个Block

typedef enum {FLASH_BUFFER1=0, FLASH_BUFFER2} FLASH_BUFFER_NUM;


#define FLASH_PAGE_COUNT   4096 // 0..4095
#define FLASH_PAGE_SIZE    512
#define FLASH_SIZE_KBYTE   2112

#define SPI_Data_Flash_HZ_SELECT()  GPIO_ResetBits(GPIOC, GPIO_Pin_13)       /* AT45db161 CS = L */
#define SPI_Data_Flash_HZ_DESELECT()  GPIO_SetBits(GPIOC, GPIO_Pin_13)         /* AT45db161 CS = H */

// set Page (12Bit) and Byte Address (10Bit)
#define ADR_P_B_1(page)    (unsigned char)(page>>6)    // 2 res.bits + 6 bits of 12-bit page-address
#define ADR_P_B_2(page, address) (unsigned char)(page<<2)|(address>>8) // 6 bit page-address and 2bit Byte-address
#define ADR_P_B_3(address)      (unsigned char)address     // 8 bit Byte-address

// set Byte Address (10Bit)
#define ADR_B_1(address)      (unsigned char)(address>>8)    // 6 don't care + Bit8,9 of address (2bit address)
#define ADR_B_2(address)   (unsigned char)(address)    // bit7 .. Bit0 of address (8bit address)

// set Page Address (12Bit)
#define ADR_P_1(page)    (unsigned char)(page>>6)    // 2 res.bits + 6 bits of 12-bit page-address
#define ADR_P_2(page)    ((unsigned char)(page))<<2    // 6 bit of 12-bit page-address + 2 don't care

/************************************************************************
** 函数名称:void Data_FLASH_HZ_SPI_Config(void)
** 功能描述: 配置STM32F10*与Data Flash 汉字库相关的GPIO引脚 为SPI引脚
** 输 入:
** 输 出:    无
** 全局变量:
** 调用模块:
*****************************************/

void Data_FLASH_HZ_SPI_Config(void)
{
    SPI_InitTypeDef  SPI_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC  | RCC_APB2Periph_GPIOA|
            RCC_APB2Periph_AFIO |
            RCC_APB2Periph_SPI1,
            ENABLE);

    /* SCK, MISO and MOSI  A5=CLK,A6=MISO,A7=MOSI*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /*  PC.13 作片选*/
 GPIO_SetBits(GPIOC, GPIO_Pin_13);//预置为高
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    /* SPI1 configuration  */
 SPI_Cmd(SPI1, DISABLE);             //必须先禁能,才能改变MODE
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //两线全双工
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;       //主
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;      //8位
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;        //CPOL=0 时钟悬空低
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;       //CPHA=0 数据捕获第1个
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;        //软件NSS
   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;  //4分频
 //    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;  //16分频

    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;      //高位在前
    SPI_InitStructure.SPI_CRCPolynomial = 7;        //CRC7
   
 SPI_Init(SPI1, &SPI_InitStructure);
 //SPI_SSOutputCmd(SPI1, ENABLE); //使能NSS脚可用
    SPI_Cmd(SPI1, ENABLE);
 
}


/************************************************************************
** 函数名称:static u8 SPI_ReadWrite_Byte(u8 byte)
** 功能描述:  发送或者接收1个字节
** 输 入:    byte    发送时候,byte传递为发送的数据字节, 接收的时候,则固定为0xff
** 输 出:    SPI1->DR  发送时候,可以忽略, 接收的时候,则为接收数据
** 全局变量:
** 调用模块:
***********************************************************************/

static u8 SPI_ReadWrite_Byte(u8 byte)
{
 /*等待发送寄存器空*/
 while((SPI1->SR & SPI_I2S_FLAG_TXE)==RESET);
    /*发送一个字节*/
 SPI1->DR = byte;
 /* 等待接收寄存器有效*/
 while((SPI1->SR & SPI_I2S_FLAG_RXNE)==RESET);
 return(SPI1->DR);
}


 

/*********************************************************************
// Description   : Returns Flash Status Byte
// Input         : none
// Output      : unsigned char - status-Byte
// Indication  : see "Status Register Read"
// **********************************************************************************
u8 Dataflash_read_status(void)
{
 u8 data;

 SPI_Data_Flash_HZ_SELECT(); //片选Dataflash
 SPI_ReadWrite_Byte(AT45DB_READ_STATE_REGISTER);
 data = SPI_ReadWrite_Byte(0x00);
 SPI_Data_Flash_HZ_DESELECT();
 return data;
}

 /**********************************
 Data Flash  检测忙
**********************************/ 
 #define AT45DB_DATAFLASH_BUSY_BIT    0x80
u8 SPI_Data_Flash_Busy_Detect(void)
{
 u16 i=0;

 
 if((Dataflash_read_status() & AT45DB_DATAFLASH_BUSY_BIT) == 0)
 {
      for(i=0;i<0xff;i++);
  if((Dataflash_read_status() & AT45DB_DATAFLASH_BUSY_BIT) == 0)
  return 1;   //忙返回1
 else
  return 0;
 }
 else
 {
  return 0;   //空闲返回0
 }
}
/*************************************
** 函数名称: u8 Dataflash_read_flash2buffer(FLASH_BUFFER_NUM buffer_num, unsigned int page)
** 功能描述:  设定AT45DB161在读取的时候,将数据送往内部的1号Buffer或者 2号
** 输入    :  buffer_num - number of buffer to transfer
**                    Buffer 1 - 0
**                    Buffer 2 - 1  
**         :  page   - page address in main memory
** 输出      : 1 - OK
**    : 0 - read error
** 全局变量:
** 调用模块:
*************************************/

u8 Dataflash_read_flash2buffer(FLASH_BUFFER_NUM buffer_num, u16 page)
{
 if(SPI_Data_Flash_Busy_Detect()==0)  //==0 Data Flash空闲
 {
 SPI_Data_Flash_HZ_SELECT(); //片选Dataflash if (buffer_num == FLASH_BUFFER1)
 if (buffer_num == FLASH_BUFFER1)
  SPI_ReadWrite_Byte(AT45DB_MM_PAGE_TO_B1_XFER);
 else
  SPI_ReadWrite_Byte(AT45DB_MM_PAGE_TO_B2_XFER);                  // 8-bit opcode
 SPI_ReadWrite_Byte(ADR_P_1(page)); 
 SPI_ReadWrite_Byte(ADR_P_2(page));
 SPI_ReadWrite_Byte(0x00);      // 8 don't care bits
 SPI_Data_Flash_HZ_DESELECT();
 return 1;
 }
 return 0;
}
/*************************************
** 函数名称: void DataFlashPageRead(u16 page,u8 *Data)
** 功能描述:  读取AT45DB161内部页数据
** 输入    :  
**         :  page   - page address in main memory
**         :  Data   - Adresse im Buffer
** 输出    :  

** 全局变量:
** 调用模块:
*************************************/
//void DataFlashPageRead(u16 page,u8 *Data)
void DataFlashPageRead(unsigned int page,unsigned char * pHeader)
{
/*
 u16 i; 
 while(SPI_Data_Flash_Busy_Detect());
 SPI_Data_Flash_HZ_SELECT(); //片选Dataflash if (buffer_num == FLASH_BUFFER1)
 SPI_ReadWrite_Byte(AT45DB_MM_PAGE_READ);
 SPI_ReadWrite_Byte((u8)(page >> 6));
   SPI_ReadWrite_Byte((u8)(page << 2));
   SPI_ReadWrite_Byte(0x00);//3个字节

  for (i = 0;i < 528; i++)
 {
  Data[i] = SPI_ReadWrite_Byte(0x00);
 }
 SPI_Data_Flash_HZ_DESELECT();
 */
    unsigned int i=0;

 while(SPI_Data_Flash_Busy_Detect());

 SPI_Data_Flash_HZ_SELECT(); 
    SPI_ReadWrite_Byte(AT45DB_MM_PAGE_TO_B1_XFER);
    SPI_ReadWrite_Byte((unsigned char)(page >> 6));
    SPI_ReadWrite_Byte((unsigned char)(page << 2));
    SPI_ReadWrite_Byte(0x00);
 SPI_Data_Flash_HZ_DESELECT();

 while(SPI_Data_Flash_Busy_Detect());

 SPI_Data_Flash_HZ_SELECT(); 
    SPI_ReadWrite_Byte(AT45DB_BUFFER_1_READ);
    SPI_ReadWrite_Byte(0x00);
    SPI_ReadWrite_Byte(0x00);
    SPI_ReadWrite_Byte(0x00);
    SPI_ReadWrite_Byte(0x00);
    for (i=0; i<512; i++)
    {
        *pHeader++ = SPI_ReadWrite_Byte(0x00);
    }
 SPI_Data_Flash_HZ_DESELECT(); 
  
}

/*************************************
** 函数名称: void FlashPageWrite(u16 page,u8 *Data)  //写一整页,页范围0-4095
** 功能描述:  将数据写入AT45DB161内部页存储空间
** 输入    :  
**         :  page   - page address in main memory
**         :  Data   - Adresse im Buffer
** 输出    :  
** 全局变量:
** 调用模块:
*************************************/
void FlashPageWrite(u16 page,u8 *Data)  //写一整页,页范围0-4095
{
 u16 i;
 while(SPI_Data_Flash_Busy_Detect());

 SPI_Data_Flash_HZ_SELECT(); //片选Dataflash if (buffer_num == FLASH_BUFFER1)

 SPI_ReadWrite_Byte(AT45DB_BUFFER_2_WRITE);
 SPI_ReadWrite_Byte(0x00);
 SPI_ReadWrite_Byte(0x00);
 SPI_ReadWrite_Byte(0x00);
 for (i = 0;i < 512; i++)
 {
  SPI_ReadWrite_Byte(Data[i]);
 }
 SPI_Data_Flash_HZ_DESELECT(); 

  while(SPI_Data_Flash_Busy_Detect());  
 if ( page < 4096)
 {
  SPI_Data_Flash_HZ_SELECT(); //片选Dataflash if (buffer_num == FLASH_BUFFER1)
  SPI_ReadWrite_Byte(AT45DB_B2_TO_MM_PAGE_PROG_WITH_ERASE);
  SPI_ReadWrite_Byte((u8)(page>>6));
  SPI_ReadWrite_Byte((u8)(page<<2));
  SPI_ReadWrite_Byte(0x00);


  while(SPI_Data_Flash_Busy_Detect());
  SPI_Data_Flash_HZ_DESELECT();  } 
}

/*************************************
** 函数名称:u8 Dataflash_read_buffer(u8* data, u16 address, u16 size, FLASH_BUFFER_NUM buffer_num)
** 功能描述: 连续读AT45DB161内部缓冲区1或者缓冲区2的数据
 
** 输 入:      : data - Pointer to buffer inside of SRAM from Microcontroller
**              : address - Adresse im Buffer
**              : size - count of Byte
**              : buffer_num - Buffer 1 - 0
**              :              Buffer 2 - 1  

** 输出      : 1 - OK
**    : 0 - read error
** 全局变量:
** 调用模块:
*************************************/
u8 Dataflash_read_buffer(u8* data, u16 address, u16 size, FLASH_BUFFER_NUM buffer_num)
{
 u16 i;

 if(SPI_Data_Flash_Busy_Detect()==0)  //==0 Data Flash空闲
 {
  SPI_Data_Flash_HZ_SELECT(); //片选Dataflash if (buffer_num == FLASH_BUFFER1)
  if (buffer_num == FLASH_BUFFER1)
  {
   SPI_ReadWrite_Byte(AT45DB_BUFFER_1_READ);
  }
  else
  {
   SPI_ReadWrite_Byte(AT45DB_BUFFER_2_READ);
  }

 // SPI_ReadWrite_Byte(ADR_P_1(address));
 // SPI_ReadWrite_Byte(ADR_P_2(address));
  SPI_ReadWrite_Byte(0x00);
   SPI_ReadWrite_Byte(0x00);
  SPI_ReadWrite_Byte(0x00);                        // 8 don't care
  for (i=0; i<size; i++)              
   data[i] = SPI_ReadWrite_Byte(0x00);
  SPI_Data_Flash_HZ_DESELECT();
  return 1;
 }
 else  //总线忙
 {
  return 0;
 }
}


/*************************************
** 函数名称:u8 dataflash_write2flash(unsigned char* data, unsigned int page, unsigned int address, unsigned int size, FLASH_BUFFER_NUM buffer_num)
** 功能描述: 连续写数据到SPI Flash内部 
** 输 入:      : data - Pointer to buffer inside of SRAM from Microcontroller
**              : address - Adresse im Buffer
**              : size - count of Byte
**              : buffer_num - Buffer 1 - 0
**              :              Buffer 2 - 1  

** 输出      : 1 - OK
**    : 0 - read error
** 全局变量:
** 调用模块:
*************************************/

u8 Dataflash_write2flash(u8* data, u16 page,  u16 address,  u16 size, FLASH_BUFFER_NUM buffer_num)
{
 u16 i;

 if(SPI_Data_Flash_Busy_Detect()==0)  //==0 Data Flash空闲
    {
 SPI_Data_Flash_HZ_SELECT(); //片选Dataflash 
 if(buffer_num == FLASH_BUFFER1)
  SPI_ReadWrite_Byte(AT45DB_BUFFER_1_WRITE );
 else
  SPI_ReadWrite_Byte(AT45DB_BUFFER_2_WRITE);
/* SPI_ReadWrite_Byte(ADR_P_B_1(page));
 SPI_ReadWrite_Byte(ADR_P_B_2(page, address)); 
 SPI_ReadWrite_Byte(ADR_P_B_3(address)); */
 SPI_ReadWrite_Byte(ADR_P_1(page));
 SPI_ReadWrite_Byte(ADR_P_2(page)); 
 SPI_ReadWrite_Byte(0x00);


 for (i=0; i<size; i++)              
  SPI_ReadWrite_Byte(data[i]);
 SPI_Data_Flash_HZ_DESELECT();
 return 1;
 }
return 0;
}
 /***********************************************************************

- 功能描述:从某一页的某个位置开始读取一定长度的数据,放入数据缓冲区

- 隶属模块:AT45DB161模块

- 函数属性:外部,供用户调用

- 参数说明:addr:扇区地址

             start:扇区内的起始位置

    len:要读取的数据长度

    pbuf:指向数据缓冲中的指针

- 返回说明:无

- 注:无

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

void AT45DB161_ReadBytes(unsigned int addr,unsigned int start,unsigned int len,unsigned char *pbuf)

{    

 unsigned int i;    

 while(SPI_Data_Flash_Busy_Detect()==1);  //==0 Data Flash空闲
 SPI_Data_Flash_HZ_SELECT(); //片选Dataflash 
 SPI_ReadWrite_Byte(0xe8);  
 SPI_ReadWrite_Byte((unsigned char)(addr>>6));  
 SPI_ReadWrite_Byte((unsigned char)((addr<<2)|(start>>8)));
 SPI_ReadWrite_Byte((unsigned char)start);
 for(i=0;i<4;i++) SPI_ReadWrite_Byte(0x00);
 for(i=0;i<len;i++) pbuf[i]=SPI_ReadWrite_Byte(0x00);
 SPI_Data_Flash_HZ_DESELECT();

}
/************************************************************************
** 函数名称:void Dataflash_erase_page(u16 page)
** 功能描述: 删除对应的页  每页对应512Byte
** 输 入:    无
** 输 出:    无
** 全局变量:
** 调用模块:
***********************************************************************/


void Dataflash_erase_page(u16 page)
{
 while(SPI_Data_Flash_Busy_Detect());
 
 SPI_Data_Flash_HZ_SELECT(); //片选Dataflash
 SPI_ReadWrite_Byte(AT45DB_PAGE_ERASE);
 SPI_ReadWrite_Byte(ADR_P_1(page)); 
 SPI_ReadWrite_Byte(ADR_P_2(page));
 SPI_ReadWrite_Byte(0x00);                       // 8 don't care bits
 SPI_Data_Flash_HZ_DESELECT();

}


/************************************************************************
** 函数名称:void Dataflash_erase_block(u16 page)
** 功能描述: DataFlash AT45DB161 块删除,每一块对应4KByte
** 输 入:    无
** 输 出:    无
** 全局变量:
** 调用模块:
************************************************************************/
void Dataflash_erase_block(u16 page)
{
 while(SPI_Data_Flash_Busy_Detect());

 SPI_Data_Flash_HZ_SELECT(); //片选Dataflash
 SPI_ReadWrite_Byte(AT45DB_BLACK_ERASE);
 SPI_ReadWrite_Byte(ADR_P_1(page)); 
 SPI_ReadWrite_Byte(ADR_P_2(page));
 SPI_ReadWrite_Byte(0x00);                  // 8 don't care bits
 SPI_Data_Flash_HZ_DESELECT();
}

 

_______________________________________________________

 

2. 写入字库文件的方法:

1)建立2个容量为512Byte的缓冲数组Buffer1、Buffer2。串口中断中,先将第一个缓冲数组Buffer1填满,填满了512Byte内容,则发送一个消息到负责写入数据的任务,同时将中断接收到的数据放入第二个缓冲数组Buffer2中;

2)在任务中将缓冲数组Buffer1里面数据作为1 page的内容写入制定的page address。(AT45DB161 1 Page 大小为512/528Byte)。将Buffer1中的内容清零。

3)Buffer2满了以后,同样发送一个对应的消息到负责写入数据的任务,同时将中断接收到的数据放入第1个缓冲数组Buffer1中;

4)在任务中将缓冲数组Buffer2里面数据作为1 page的内容写入制定的page address。将Buffer2中的内容清零。

5)按照上面的循环,同时指定写入的Page address是要依次递增的。

6)在烧录的过程中,设定一个定时器,两个缓冲Buffer1、Buffer2在中断服务程序中切换使用的时候,将定时器复位,重新开始计时;当上位机没有字库文件发送到串口的时候,(发送完毕了)超过一定时间定时器中断调用中断服务程序,在服务程序中将Buffer1或者Buffer2的数据写入指定的Page address。(Buffer1或者Buffer2内部的数据小于512Byte的时候,写入数据的任务是不会有写入动作的,所以要在定时器服务程序中进行)

 

 

特别注意: 

1.在Buffer1、Buffer2没有使用互斥的信号量的情况下,写入数据的任务必须保证不被其他任务打断,否则有可能Buffer1中的数据还没有被完成写入的情况下,就会被串口接收中断程序改写,导致丢失数据。(最好是增加一个互斥信号量,但是会显得复杂些。上位机的通信没有串口握手信号的情况下,两个Buffer都满,并且写入任务还没有释放一个Buffer信号量的情况下,同样会丢失数据,导致字库文件出错。丢失数据的位置并不固定,有时候前5KByte都正常,后面就出错,有时候则1KByte正常,后面出错)

2. 我在项目中实际处理方式是,没有采用信号量互斥处理,而是当目标板进入了字库烧录状态,就将系统其他周期性的任务挂起,确保写入任务能够得到足够的时间运行。烧录、校验完成以后,再恢复其他任务(好在字库烧录状态只是很少情况下使用)
 

 

-----------------------------------------------

AT45DB161 字库寻址方式:

 

1. 参考了网上很多代码和文章,都说以下公式是汉字库寻址地址计算公式:

                 
address=(94*(hz[0]-0xa0-1)+(hz[1]-0xa0-1))*HZ_BYTES;//得到偏移位置

 

但是我用这个公式死活不能得到正确的显示数据,将以上公式改为如下即可:

address=(94*(hz[0]-0xb0)+(hz[1]-0xa0-1))*HZ_BYTES;//得到地址

 

具体原因不明,没有仔细研究汉字库的区别。是参考www.daxia.com/bbs论坛中DX32开发板在SST25FV08 Data Flash字库寻址公式。

 

2. 在AT45DB161字库读取的时候采用了整page读取之后再取对应数据的方法。程序代码如下:

  hz是汉字的区位码。(0xXXXX,16bit)

 u8 c1,c2;
 u32 addr;
 u16 HZ_page;
 u16 HZ_offset;
 u8 HZ_buffer[528];
 u16 _HZ16_Buf[16];//汉字字库缓冲
 u16 _HZ16_Buf2[32];

 

 c1=(u8)hz;   //获取区码
 c2=hz>>8;   //获取位码
 addr=(HZ_DOT16_START_ADDR*512)+((c1-0xb0)*94+(c2-0xa1))*32;  // ((区码-1)*94+(位码-1))*32
 HZ_offset =addr%512;
 HZ_page  =addr/512;
 

 DataFlashPageRead(HZ_page,&HZ_buffer[0]);
 for(i=0,j=0;i<16;i++,j=j+2)
 {
  _HZ16_Buf[i]=HZ_buffer[HZ_offset+1+j ];

  _HZ16_Buf[i]=_HZ16_Buf[i]<<8;
  _HZ16_Buf[i]=_HZ16_Buf[i]|HZ_buffer[HZ_offset+j];
 }

在AT45DB161中存储的点阵数据低8bit在前,高8bit在后。所以读取出来的时候要先将高8bit数据放到显示缓冲数组_HZ16_Buf[i]的高8bit;否则显示出来的字符有点异样。

 

或者用此AT45DB161读取函数也可,这个函数读取指定位置的字符,不是整页整页的读取。(注意_HZ16_Buf2这里要强制转换成为(u8*)类型,强制转换以后,在AT45DB161函数执行过程中,自动会将第一个SPI操作读取的8bit数据放入_HZ16_Buf2内部的低8bit;将第二个SPI操作读取到的8bit数据放入_HZ16_Buf2内部的高8bit,省去了转换的麻烦。

 

 AT45DB161_ReadBytes(HZ_page,HZ_offset,32,(u8*)_HZ16_Buf2);

 

 

----------

以上是对AT45DB161烧录、读取16*16类型字库文件实际编程中的一点经验。


  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值