AVR读取字库芯片GT30L16M2Y信息总是0xff

2019-07-15 18:44发布

说明:这是模拟SPI协议读取字库点阵信息,但是读出的数据全是高电平,真的无从下手。希望大家帮帮忙。谢谢!

/*这个是源代码,用的是SPI协议*/

#include    <stdio.h>
#include  "lcd.h"
#include "hal.h"
#include "hwclock.h"
#include  <avr/io.h>
#include  <avr/iom1280.h>
#include  <avr/interrupt.h>
#include  <avr/pgmspace.h>
#include    "ZKchip.h"
/*计算要读取的汉字点阵的字节地址
12x12 点阵字库地址分配(字节地址):0000 0000 H ~ 000A 76FF H,
地址的计算由下面的函数实现(ANSI C  语言编写)
*/
/***************************************************************************************************
函数:unsigned long gt(unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4)
功能:计算汉字点阵在芯片中的地址
参数: c1,c2,c3,c4: 4 字节汉字内码通过参数 c1,c2,c3,c4 传入,双字节内码通过参数 c1,c2 传入, c3=0,c4=0
返回:汉字点阵的字节地址(byte  address)。如果用户是按  word  mode  读取点阵数据,则其地址(word
address)为字节地址除以 2,即:word address = byte address / 2 .
例如:BaseAdd:  说明汉字点阵数据在字库芯片中的起始地址,即 BaseAdd=0x0000;
“啊”字的内码为 0xb0a1,则 byte address = gt(0xb0,0xa1,0x00,0x00) *24+BaseAdd
word address = byte address / 2
“   ”字的内码为 0x8139ee39,则 byte address = gt(0x81,0x39,0xee,0x39) *24+ BaseAdd
word address = byte address / 2
****************************************************************************************************/
static uint32_t gt(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4)
{
uint32_t h=0;
if(c2==0x7f)
{
  return (h);
}
            
if(c1>=0xA1 && c1 <= 0Xa9 && c2>=0xa1)       //Section 1
{
  h= (c1 - 0xA1) * 94 + (c2 - 0xA1);
}
else if(c1>=0xa8 && c1 <= 0xa9 && c2<0xa1)     //Section 5
{
  if(c2>0x7f)
  c2--;                              
  h=(c1-0xa8)*96 + (c2-0x40)+846;  
}
if(c1>=0xb0 && c1 <= 0xf7 && c2>=0xa1)       //Section 2
{
  h= (c1 - 0xB0) * 94 + (c2 - 0xA1)+1038;
}
else if(c1<0xa1 && c1>=0x81 && c2>=0x40 )     //Section 3
{
  if(c2>0x7f)
  c2--;
  h=(c1-0x81)*190 + (c2-0x40) + 1038 +6768;
}
else if(c1>=0xaa && c2<0xa1)                 //Section 4
{
  if(c2>0x7f)
  c2--;                              
  h=(c1-0xaa)*96 + (c2-0x40) + 1038 +12848;
}
else if(c1==0x81 && c2>=0x39) //四字节区 1
{
  h =1038 + 21008+(c3-0xEE)*10+c4-0x39;
}
else if(c1==0x82)//四字节区 2
{
  h =1038 + 21008+161+(c2-0x30)*1260+(c3-0x81)*10+c4-0x30;
}
return(h);
}

/*功能:计算出来要读取的汉字的字节首地址*/
/*返回值:汉字的信息首地址*/
/*参数:4个字节的汉字内码*/
uint32_t cal_ZKbyte(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4)
{
    uint32_t byteaddress = 0;
   
    byteaddress = gt(c1,c2,c3,c4)*24 + BASEADD;        //此计算方法详见数据手册
   
    return byteaddress;
}
/*向字库芯片中写入一个字节的数据*/
void write_ZKbyte(uint8_t dat)
{
     uint8_t i;
     for(i=0;i<8;i++)
     {
            ZK_SCLK_0();
            if(dat&0x80)
            {
                  ZK_SI_1();  
            }
            else
            {
                 ZK_SI_0();
            }
            dat = dat<<1;
            ZK_SCLK_1();
     }
}
/*从字库芯片中读取一个字节的数据*/
uint8_t read_ZKbyte(void)
{
     uint8_t temp = 0;
     uint8_t i;
    ZK_SCLK_1();
    for(i=0;i<8;i++)
    {  
        ZK_SCLK_0();
        temp = (temp<<1);
        if(IS_SO_1)            //判断ZK_SO端口的电平
        temp++;
        
        ZK_SCLK_1(); //
    }  
    return (temp);
   
     
}

/*函数功能:读出字库芯片中存放的点阵信息*/
/*函数的参数:4个字节的汉字内码c1~c4,要读取的字节数length,存放读取到的信息的数组指针*ptr*/
void read_ZK(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4, uint8_t length, uint8_t *ptr)
{
    uint32_t byteaddress = 0;
    uint8_t byteaddress1,byteaddress2,byteaddress3;    //代表要传送的三个地址信息                                                                  
    //uint8_t dummybyte = 0xaa;//代表最后传送的虚拟地址
    uint8_t cmd = 0x03;
    uint8_t i;
   
    ZK_PIN_INIT();              //初始化与字库芯片相关的引脚

   
    byteaddress = cal_ZKbyte(c1, c2, c3, c4);   //计算出点阵在芯片中的首字节地址
    byteaddress1 =( (uint8_t)(byteaddress>>16)&0xff);    //存放16-23位地址
    byteaddress2 =  ((uint8_t)(byteaddress>>8)&0xff);    //存放8-15位地址
    byteaddress3 =   ((uint8_t)(byteaddress>>0)&0xff);    //存放0-7位地址
   
    ENTER_TASK;                             //关闭所有的中断源,等待数据读取完毕
     ZK_CS_1();
     ZK_SCLK_1();
     ZK_SI_1();
     ZK_CS_0();
      ZK_SCLK_0();
     /*向字库芯片中写入命令和三个字节的地址信息*/
     
     write_ZKbyte(cmd);
     write_ZKbyte(byteaddress1);
     write_ZKbyte(byteaddress2);
     write_ZKbyte(byteaddress3);
     
     //write_ZKbyte(dummybyte);
     /*接下来就读取字库芯片传给我们的点阵信息*/
     for(i=0;i<length;i++)
     {
             *ptr  =  read_ZKbyte();
             ptr++;
     }
     
     //读取完成之后,就将片选信号关闭
     ZK_CS_1();
     LEAVE_TASK;                                             //打开中断源,恢复所有的中断
        
}

/*这个是头文件*/
#ifndef __ZKCHIP_H__
#define __ZKCHIP_H__

/*以atmega1280为参考*/
#define  ZK_SPI_PORT  PORTK
#define  ZK_SPI_DIR  DDRK

/*此处,需要将PK1、PK3、PK4设置为输出;将PK2设置为输入*/
#define  ZK_CS         1
#define  ZK_SO        2
#define  ZK_SI         3
#define  ZK_SCLK   4

#define ZK_PIN_INIT() do{ZK_SPI_DIR|=((1<<ZK_CS )|(1<<ZK_SI)|(1<<ZK_SCLK));ZK_SPI_DIR&=~(1<<ZK_SO);}while(0)
#define IS_SO_1          (PINK&(1<<ZK_SO))

#define  ZK_CS_0()   (ZK_SPI_PORT&=~(1<<ZK_CS ))
#define  ZK_CS_1()   (ZK_SPI_PORT|=(1<<ZK_CS ))
#define  ZK_SI_0()   (ZK_SPI_PORT&=~(1<<ZK_SI ))
#define  ZK_SI_1()   (ZK_SPI_PORT|=(1<<ZK_SI))
#define  ZK_SCLK_0()   (ZK_SPI_PORT&=~(1<<ZK_SCLK ))
#define  ZK_SCLK_1()   (ZK_SPI_PORT|=(1<<ZK_SCLK ))

/*设置12X12点阵在芯片中的起始地址*/
#define BASEADD 0x0000

/*函数功能:读出字库芯片中存放的点阵信息*/
/*函数的参数:4个字节的汉字内码c1~c4,要读取的字节数length,存放读取到的信息的数组指针*ptr*/
void read_ZK(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4, uint8_t length, uint8_t *ptr);

#endif




友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。