打印
[Atmel]

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

[复制链接]
2657|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
chenhengjin|  楼主 | 2014-8-21 09:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
说明:这是模拟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



相关帖子

沙发
NE5532| | 2014-8-21 11:04 | 只看该作者
把字库芯片拆掉,找个小电阻(10Ohm左右的)把MISO线短路到地,再读,看是00还是FF,多半读回来的是上拉电阻,而不是数据。先调试发送,用示波器看波形,再调试接收,想办法证明自己的上一步是正确的。搜本版精华帖《程序调试黑宝书》

使用特权

评论回复
板凳
ddllxxrr| | 2014-8-21 20:12 | 只看该作者
读出全是FF,有两种情况,要么时序没有模对,要么地址错了。我想楼主应先读一下芯片的一个地址。保证读出不全是FF再把程序加上

使用特权

评论回复
地板
NE5532| | 2014-8-22 22:36 | 只看该作者
应该是先读一个明显不为FF的,最好是确定的东西,比如芯片版本寄存器之类。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

5

帖子

0

粉丝