说明:这是模拟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
****************************************************************************************************/
sta
tic 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
一周热门 更多>