1、(一)原理图
2、AVR单片机+32*64点阵屏驱动记录(二)简单驱动-CSDN博客
3、AVR单片机+32*64点阵屏驱动记录(三)程序烧写-CSDN博客
4、AVR单片机+32*64点阵屏驱动记录(四)字库读取_修充电器上瘾的博客-CSDN博客
5、AVR单片机+32*64点阵屏驱动记录(五)字库研究一言难尽_修充电器上瘾的博客-CSDN博客
6、AVR单片机+32*64点阵屏驱动记录(六)GB2312字库读取-CSDN博客
一、源码
main.c
#include <iom64v.h>
#include <macros.h>
#include <string.h>
#include "uart.h"
int a16=0,a17=0;
#define FLASH_ADDR_BASE 0x2000
//595移位寄存器
#define DS_SET PORTB|= BIT(2); //595_DS:PB2
#define DS_CLR PORTB&=~BIT(2);
#define STCP0_SET PORTG|=BIT(3); //595_STCP:PG3
#define STCP0_CLR PORTG&=~BIT(3);
#define STCP1_SET PORTG|=BIT(4); //595_STCP:PG4
#define STCP1_CLR PORTG&=~BIT(4);
#define SHCP_SET PORTB|=BIT(1); //595_SHCP:PB1
#define SHCP_CLR PORTB&=~BIT(1);
//74HC154译码器使能低电平有效
#define DECODER0_E1_SET PORTD|=BIT(0); //74HC154D_E1:PD0
#define DECODER0_E1_CLR PORTD&=~BIT(0);
#define DECODER1_E1_SET PORTD|=BIT(1); //74HC154D_E1:PD1
#define DECODER1_E1_CLR PORTD&=~BIT(1);
//字库高位A16、A17
#define EEPROM_A16_SET PORTD|=BIT(6);
#define EEPROM_A16_CLR PORTD&=~BIT(6);
#define EEPROM_A17_SET PORTD|=BIT(7);
#define EEPROM_A17_CLR PORTD&=~BIT(7);
//PD4
#define EEPROM_CE_SET PORTD|=BIT(4);
#define EEPROM_CE_CLR PORTD&=~BIT(4);
//PG0 0x65
#define WRL (PORTG=PORTG&0XFE)
#define WRH (PORTG=PORTG|0X01)
//PG1
#define RDL (PORTG=PORTG&0XFD)
#define RDH (PORTG=PORTG|0X02)
//PG2
#define ALEL (PORTG=PORTG&0XFB)
#define ALEH (PORTG=PORTG|0X04)
unsigned char Table_BUFF[256];
unsigned short iHZ=0;
const unsigned char str="\xB0\xA1\xB0\xA2\xB2\xEF\xB2\xF0\xEF\xB9\xEB\xE7\xB0\xCB\xC6\xDF\0";
//unsigned char *str="一二三四五六七八九十百千一二三四五六七八九十百千一二三四五六七八九十百千一二三四五六七八九十百千一二三四五六七八九十百千";
unsigned short pStr=0;
const unsigned char Table_row[] = {
0xFF,0xBF,0xBF,0xBF,0xDF,0xBF,0xDF,0xBB,
0xFF,0x97,0xF8,0x8F,0xEE,0x9F,0xEE,0xAF,
0xDE,0xAF,0x1D,0xB7,0xDD,0xB7,0xDB,0xBB,
0xD7,0xBD,0xDF,0xBF,0xDE,0xBF,0xFF,0x7F,/*"冰",0*/
0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xF7,
0xFE,0xF7,0x82,0x6F,0xFA,0x5F,0xF6,0xBF,
0xF6,0xBF,0xEE,0xDF,0xEE,0xEF,0xDE,0xF7,
0xBE,0xF9,0x7E,0xFF,0xFA,0xFF,0xFD,0xFF,/*"水",1*/
0xFE,0xFF,0xDE,0xFF,0xEE,0xFF,0xEE,0xFF,
0xFE,0xFF,0x80,0x07,0xFD,0xF7,0xFD,0xF7,
0xFD,0x77,0xFB,0xB7,0xFB,0xB7,0xF7,0xF7,
0xEF,0xF7,0xDF,0xF7,0xBF,0xAF,0x7F,0xDF,/*"为",2*/
0xFD,0xFF,0xFE,0xFF,0xFE,0xFF,0xFF,0xFF,
0x80,0x07,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,
0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,
0xE7,0xFF,0xDB,0xFF,0xBC,0x01,0xFF,0xFF,/*"之",3*/
0xFF,0xFF,0x80,0x03,0xFE,0xFF,0xFE,0xFF,
0xFD,0xFF,0xC0,0x07,0xDB,0x77,0xDB,0x77,
0xDB,0x77,0xDB,0x77,0xDB,0x77,0xDB,0x77,
0xDB,0x77,0xDB,0x77,0xDF,0xD7,0xDF,0xEF,/*"而",4*/
0xFD,0xFF,0xFE,0xFF,0x80,0x01,0xBB,0xBD,
0x60,0x0B,0xFB,0xBF,0xC0,0x07,0xFB,0xBF,
0x00,0x01,0xF7,0xDF,0xEC,0xEF,0xDF,0x77,
0x3F,0xB9,0xF9,0xFF,0xFE,0x7F,0xFF,0xBF,/*"寒",5*/
0xFF,0xFF,0xC0,0x07,0xFE,0xFF,0xFE,0xFF,
0xFE,0xFF,0xFE,0xFF,0x00,0x01,0xFE,0xFF,
0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,
0xFE,0xFF,0xFE,0xFF,0xFA,0xFF,0xFD,0xFF,/*"于",6*/
0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xF7,
0xFE,0xF7,0x82,0x6F,0xFA,0x5F,0xF6,0xBF,
0xF6,0xBF,0xEE,0xDF,0xEE,0xEF,0xDE,0xF7,
0xBE,0xF9,0x7E,0xFF,0xFA,0xFF,0xFD,0xFF,/*"水",7*/
};
void Delay1ms(void)
{
unsigned int i;
for(i=0;i<=(unsigned int)(16*143-2);i++);
}
void delayms(unsigned int m)
{
unsigned char i;
for(i=0;i<=m;i++)
Delay1ms();
}
void gpio_init(void)
{
DDRA = 0xFF;
DDRC = 0xFF;
DDRB = 0xFF; /* output */
DDRG = 0XFF;
DDRE = 0XFF;
DDRD = 0XFF;
}
//按地址从FLASH(EEPROM)中读一个字节
unsigned char FlashRead(unsigned short offset)
{
unsigned char *p;
unsigned char ch=0xAA;
unsigned short pos;
if(a16){
EEPROM_A16_SET;
}else{
EEPROM_A16_CLR;
}
if(a17){
EEPROM_A17_SET;
}else{
EEPROM_A17_CLR;
}
pos=FLASH_ADDR_BASE+offset;
p=(unsigned char*)pos;
if((a16==0)&&(a17==0)&&(pos<0x2000)){
DDRC = 0xFF;
PORTC = 0x00;
XMCRB = (1<<XMM1) | (1<<XMM0);
ch=*p;
XMCRB = 0x00;
}else{
ch=*p;
}
putchar1(ch);
return ch;
}
void prepareBuff(void)
{
unsigned short i=0;
for(i=0;i<256;i++){
Table_BUFF[i]=FlashRead(iHZ);
iHZ=iHZ+1;
}
}
void HC595(unsigned char dat)
{
unsigned char j;
for(j=0;j<8;j++)
{
SHCP_CLR; //为移位准备
if(dat&0x80){ //先高位
DS_SET;
}
else {
DS_CLR;
}
dat=dat<<1;
SHCP_SET; //上升沿,移位
}
}
void Matrix16x16(unsigned char num)
{
unsigned char k,i;
unsigned int m,n;
unsigned char Char_num=num*32;
for(m=0;m<Char_num;m++) //为移动预留
{
for(n=0;n<4;n++)//控制显示速度,防止闪烁
{
for(k=0;k<32;k++) //行扫描
{
if(k<16){
for(i=0;i<num;i++) //控制第几个字
{
HC595(~Table_BUFF[(32*(3-i)+k)]);
HC595(~Table_BUFF[(32*(3-i)+k+16)]); //
//HC595(Table_row[(32*i+2*k+1)]);
//HC595(Table_row[(32*i+2*k+0)]);
}
STCP0_CLR;
STCP0_SET; //并行输出
//PORTE=k;
PORTE=k;
//PORTE=0x00;
DECODER0_E1_SET;
DECODER1_E1_CLR;
}else {
for(i=0;i<num;i++) //控制第几个字
{
HC595(~Table_BUFF[(32*(3-i)+k-16+32*4)]); //
HC595(~Table_BUFF[(32*(3-i)+k+32*4)]); //
//HC595(Table_row[(32*i+2*(k-16)+1+32*4)]); //
//HC595(Table_row[(32*i+2*(k-16)+32*4)]); //
}
STCP1_CLR;
STCP1_SET; //并行输出
PORTE=(k-16)<<4;
//PORTE=0x00;
DECODER0_E1_CLR;
DECODER1_E1_SET;
}
}
}
}
}
void main(void)
{
gpio_init();
uart1_init(); //uart1初始化
/*
MCUCR – MCU Control Register
Bit 7 – SRE: External SRAM/XMEM Enable
Writing SRE to one enables the External Memory Interface.The pin functions AD7:0, A15:8,
ALE, WR, and RD are activated as the alternate pin functions. The SRE bit overrides any pin
direction settings in the respective data direction registers. Writing SRE to zero, disables the
External Memory Interface and the normal pin and data direction settings are used.
#define OFFSET 0x2000
void XRAM_example(void)
{
unsigned char *p = (unsigned char *) (OFFSET + 1);
DDRC = 0xFF;
PORTC = 0x00;
XMCRB = (1<<XMM1) | (1<<XMM0);
*p = 0xaa;
XMCRB = 0x00;
*p = 0x55;
}
Table 5. Port C Pins Released as Normal Port Pins when the External Memory is Enabled
XMM2 XMM1 XMM0 # Bits for External Memory Address Released Port Pins
0 0 0 8 (Full 60 KB space) None
0 0 1 7 PC7
0 1 0 6 PC7 - PC6
0 1 1 5 PC7 - PC5
1 0 0 4 PC7 - PC4
1 0 1 3 PC7 - PC3
1 1 0 2 PC7 - PC2
1 1 1 No Address high bits Full Port C
*/
EEPROM_CE_CLR;
MCUCR|=0X80;//使能XRAM,并配制成最快速度访问
XMCRA = 0x44; //0x00 external memory
XMCRB = 0x00; //
puts1("Atmega64 staring.......");
while(1){
prepareBuff();
Matrix16x16(4);
}
}
uart.c
/* Code adapted from Atmel AVR Application Note AVR306
* Interrupt mode driver for UART.
*/
#include <iom64v.h>
#include <macros.h>
#include "uart.h"
/***********************************宏定义**********************************/
#define fosc 1600000 //板子上的晶振是16MHZ
#define baud 115200 //波特率
//38400
/****************************************************************************
函数功能:uart1初始化程序
入口参数:
出口参数:
****************************************************************************/
void uart1_init(void)
{
UCSR1B = 0x00;
UCSR1A = 0x00;
UCSR1C = (1<<UCSZ11)|(1<<UCSZ10);
UBRR1L=(fosc/16/(baud+1))%256;
UBRR1H=(fosc/16/(baud+1))/256;
UCSR1B =(1<<RXEN1)|(1<<TXEN1);
}
/****************************************************************************
函数功能:uart1发送单字节数据
入口参数:c
出口参数:
****************************************************************************/
void putchar1(unsigned char c)
{
while (!(UCSR1A&(1<<UDRE1)));
UDR1=c;
}
/****************************************************************************
函数功能:uart1接收单字节数据
入口参数:
出口参数:
****************************************************************************/
unsigned char getchar1(void)
{
while(!(UCSR1A& (1<<RXC1)));
return UDR1;
}
/****************************************************************************
函数功能:uart1发送字符串数据
入口参数:*s
出口参数:
****************************************************************************/
void puts1(char *s)
{
while (*s)
{
putchar1(*s);
s++;
}
putchar1(0x0a);
putchar1(0x0d);
}
uart.h
void uart1_init(void);
void putchar1(unsigned char c);
unsigned char getchar1(void);
void puts1(char *s);
二、说明
1、UART主要是做调试用的。PC串口调试时,波特率选:115200。板子上电时先不要连UART,等板子有显示了再连,如果板子一直没显示,用手在MCU的管脚上划一划,按reset什么的,总之老板子了,不一定哪一下就可以正常工作。
2、AVR单片机访问外部存储关键的一句:
MCUCR|=0X80;//使能XRAM,并配制成最快速度访问。
有兴趣可以查一下数据手册,把MCUCR寄存器配置好了,就可以访问外部存储。但是还有个0x2000问题,就是AVR内部和外部存储地址不是分开的,而是连续的,默认0x2000地址是内部存储,而外部存储中的0x2000以下的地址默认是不可访问的。数据手册给出了一个方法可以访问这部分地址,上面的源码中摘录了这部分,但似乎不起作用。
3、这个SST29EE020字库和之前的遇到的不太一样,1)字模取法不同,2)offset偏移计算也是不同,试了GB2312和gbk偏移算法都不行。可能和AVR外部0x2000无法访问有关,做了特殊处理。
4、因此先实现了按先后顺序读取SST29EE020字库的字模,然后显示出来的功能。下一步再继续研究字库的offset偏移计算。
5、又研究了一天偏移量,感觉不好弄,找不到规律。