将16*16点阵看作四个8*8点阵,分别点亮,快速扫描实现字幕显示
数组指针右移实现字幕向左滚动的显示效果
硬件连接:74HC595四片级联,点阵屏的行输入连接HC595第一,二级输出,列输入连接第三,四级输出。74HC595的输入,大家可以根据各自的喜好和习惯连接,然后改掉端口定义。
//定义 74HC595 在电路连接中对应的 STC89C51 I/O口
/*-- 当后续电路改变时,只需在此处更换IO口的定义即可,无需再回到函数中改变内容--*/
sbit SER = P0^0; //74HC595 字符输入端 SER
sbit SCK = P0^1; //74HC595 移位寄存器钟控端 SCK
sbit RCK = P0^2; //74HC595 并行输出钟控端 RCK
以下是我写的源码,可供大家参考
初学单片机,16*16点阵是昨天学的,还有很多理解不深刻的地方,或许有跟简单的方法,欢迎各位提出更好的意见或建议
#include <REGX52.H>
//定义一个数组存放需要显示的字符内容
unsigned char code Matrix_led[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*-- 文字: 计 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x02,0x02,0x42,0x33,0x00,0x02,0x02,0x02,0x02,0xFF,0x02,0x02,0x02,0x02,0x02,0x00,
0x00,0x00,0x00,0xFE,0x04,0x08,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
/*-- 文字: 算 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x10,0x20,0xCF,0x4A,0x6A,0x4A,0x4A,0x0A,0x2A,0xCA,0x4A,0x6A,0x4F,0x40,0x40,0x00,
0x08,0x08,0xE9,0xAA,0xBC,0xA8,0xA8,0xA8,0xA8,0xA8,0xBF,0xA8,0xE8,0x08,0x08,0x00,
/*-- 文字: 机 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x08,0x08,0x0B,0xFF,0x09,0x08,0x00,0x7F,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,0x00,
0x20,0xC0,0x00,0xFF,0x00,0xC1,0x06,0xF8,0x00,0x00,0x00,0xFC,0x02,0x02,0x1E,0x00,
/*-- 文字: 学 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x02,0x0C,0x88,0x69,0x09,0x09,0x89,0x69,0x09,0x09,0x19,0x28,0xC8,0x0A,0x0C,0x00,
0x20,0x20,0x20,0x20,0x20,0x22,0x21,0x7E,0x60,0xA0,0x20,0x20,0x20,0x20,0x20,0x00,
/*-- 文字: 院 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
0x00,0x7F,0x44,0x5A,0x61,0x08,0x30,0x24,0x24,0xA4,0x64,0x24,0x24,0x28,0x30,0x00,
0x00,0xFF,0x20,0x10,0xE0,0x01,0x82,0x8C,0xF0,0x80,0x80,0xFC,0x82,0x82,0x8E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
//定义 74HC595 在电路连接中对应的 STC89C51 I/O口
/*-- 当后续电路改变时,只需在此处更换IO口的定义即可,无需再回到函数中改变内容--*/
sbit SER = P0^0; //74HC595 字符输入端 SER
sbit SCK = P0^1; //74HC595 移位寄存器钟控端 SCK
sbit RCK = P0^2; //74HC595 并行输出钟控端 RCK
//控制四级级联 74HC595 的RCK端
unsigned char _74HC595_RCK_CTRI = 0;
//数组长度
unsigned char length = sizeof(Matrix_led) / sizeof(Matrix_led[0]);
/*------------------------------------------------------------------------------*/
//函数声明: 用户调用函数
/*------------------------------------------------------------------------------*/
void Delay1ms (unsigned char xms);
void Delay10us(unsigned int xus);
void Matrix_Led_Init( void );
void Matrix_Led_Show(unsigned char* Matrix_led_code);
void Matrix_Led_Column(unsigned char col, unsigned char led_code_col, unsigned char k);
void _74HC595_WriteByte(unsigned char led_code_col);
/*------------------------------------------------------------------------------*/
//函数定义
/*------------------------------------------------------------------------------*/
/**
* @brief 点阵屏初始化
* @param 无
* @retval 无
*/
void Matrix_Led_Init( void )
{
SCK = 1;
RCK = 1;
}
/**
* @brief 在16*16点阵屏上显示字符内容
* @param 无
* @retval 无
*/
void Matrix_Led_Show(unsigned char* Matrix_led_code)
{
unsigned char k;
unsigned char m = 0, //检测字符序列
s = 0; //防止指针越界访问
for(;s <= length - 129; Matrix_led_code++, s++)
{
m++;
if(m == 17)
{
m = 1;
Matrix_led_code += 16; //数组指针右移,每当连续显示完16帧时,跳过16个字符,跳到下一个字
}
for(k = 1; k <= 4; k++)
{
unsigned char i, i2;
for(i = 0; i <= 7;i ++) //循环,依次显示第一列到第八列
{
if((i + 8*(k - 1)) % 16 >= 16 - m)
{
i2 = i + 8*(k - 1) + 16;//当某一列显示到某个字的最后一列时,跳过16个字节,跳到下一个字
}
else
{
i2 = i + 8*(k - 1);
}
Matrix_Led_Column(i, Matrix_led_code[i2], k);
}
}
}
}
/**
* @brief 在点阵屏指定的一列上显示一个8位字符数据
* @param led_cdoe_col 要显示的一个字符数据
* @param col 说明了字符要显示在哪一列的位置上
* @retval 无
* @explain 将16*16点阵看作四个8*8点阵,依次分别显示一个屏幕上的内容,并快速刷新
*/
void Matrix_Led_Column(unsigned char col, unsigned char led_code_col, unsigned char k)
{
unsigned char i;
if(k == 1){i = 0x00;} //显示左上角
if(k == 2){i = 0x01;}//显示右上角
if(k == 3){i = 0x10;}//显示左下角
if(k == 4){i = 0x11;}//显示右下角
//选列
if(i == 0x00 || i == 0x10)
{
_74HC595_WriteByte(~0x00);
_74HC595_WriteByte(~(0x80 >> col));
}
else
{
_74HC595_WriteByte(~(0x80 >> col));
_74HC595_WriteByte(~0x00);
}
//选行
if(i == 0x00 || i == 0x01)
{
_74HC595_WriteByte(0x00);
_74HC595_WriteByte(led_code_col);
}
else
{
_74HC595_WriteByte(led_code_col);
_74HC595_WriteByte(0x00);
}
}
/**
* @brief 利用74HC595四级级联,将四个字符并行输出。
每次调用此函数时led_code_col传进一个字符,_74HC595_RCK_CTRI累加计数
每当函数中传入四个字符时并行输出,_74HC595_RCK_CTRI置0,重新计数
* @param led_cdoe_col 一个字符数据
* @retval 无
*/
void _74HC595_WriteByte(unsigned char led_code_col)
{
unsigned char i;
for(i = 0; i <= 7; i++) //将led_code_col传入的字符按位(从低位到高位)放入移位寄存器
{
SER = led_code_col & ( 0x01 << i ); //从低位到高位依次读取位数值
SCK = 0;;; //控制移位寄存器时钟,将数据送入移位寄存器
SCK = 1; //将 SCK 钟控端复位
}
_74HC595_RCK_CTRI ++; //是全局变量
//控制四级级联的74HC595 RCK端
//其初值为0,SER端每进入一个字符时,74HC595_RCK_CTRI ++
//当74HC595_RCK_CTRI == 4 时(进入四个字符)
//将RCK 置1,并行输出所有数据
//并将74HC595_RCK_CTRI置0,重新计数
if(_74HC595_RCK_CTRI >= 4) //当有4个字符数据时
{
RCK = 0;;; //通过 RCK 控制74HC595并行输出数据
RCK = 1; //RCK复位
_74HC595_RCK_CTRI = 0;
}
}
void main()
{
Matrix_Led_Init();//点阵屏初始化
while(1)
{
Matrix_Led_Show(Matrix_led);
}
}