[古董贴][共享]上传一个范例 使用595串行方式驱动的1602
最近设计 总线式 结构的时候,突发奇想,使用595级联方式扩展输出单片机输出端口。试验,成功。
随即,尝试使用595驱动1602,成功。
不敢独享,整理成了范例,拿出来和大家共享。
点击此处下载armok01101506.rar [补充说明]
------------------------------
1、该范例使用ICC编写,使用RD_ATMega8L.h头文件,支持端口位操作。
2、SerialToCollateral.h就是驱动595级联的驱动库,其功能是提供一个虚拟端口。
3、RD_LCD1602B.h 是驱动1602的头文件,他支持穿行和直接连接两种模式。
4、以上提到的头文件都需要初始化。否则无法正常使用。
RD_ATMega8L.h 初始化函数 PORTDefine() 在端口初始化的时候调用;
SerialToCollateral.h 初始化函数 无,需要硬件连接相关的描述性宏定义;
RD_LCD1602B.h 初始化函数 LCDInit() 系统初始化的时候调用。 头文件说明:
SerialToCollateral.h
#ifndef _Use_SerialToCollateral
# define _Use_SerialToCollateral
/********************************************************
*函数库说明:串行输出转为并行输出基本函数库 *
*版本: v1.0 *
*作者: 傻孩子 *
*日期: 2006年1月7日 *
*修改: 傻孩子 *
*修改日期:2006年2月09日 *
* *
*[说明] *
* 1、该头文件通过3根线连接到595实现对级联的 *
* 595进行驱动,达到扩展输出端口的作用。 *
* 2、基本支持单595和2个595级联的情况,并允许 *
* 在头文件外部自定义多个595级联的情况。当 *
* 使用外部自定义多级595连接时,只需要定义 *
* 相应的位段和虚拟端口变量即可。支持位操作*
* 3、使用的时候,可以通过查询扫描的方式,也 *
* 可以在修改虚拟端口值以后通过调用函数 *
* refreshVirtualPORT()来即时刷新(推荐)。 *
********************************************************/
/***********************
* 系 统 宏 定 义 *
***********************/
/*---------------------*
* 常 数 宏 定 义 *
*---------------------*/
#ifndef True
# define True 0x01
#endif
#ifndef False
# define False 0x00
#endif
#ifndef NULL
# define NULL 0x00
#endif
#ifndef Enable
# define Enable 0x00
#endif
#ifndef Disable
# define Disable 0x01
#endif
#ifdef _Use_8Bit_VitualPORT
struct VirtualPORT
{
unsigned BIT0:1;
unsigned BIT1:1;
unsigned BIT2:1;
unsigned BIT3:1;
unsigned BIT4:1;
unsigned BIT5:1;
unsigned BIT6:1;
unsigned BIT7:1;
};
# define VIRTUAL_BIT_COUNT 8
#endif
#ifdef _Use_16Bit_VitualPORT
struct VirtualPORT
{
unsigned BIT0:1;
unsigned BIT1:1;
unsigned BIT2:1;
unsigned BIT3:1;
unsigned BIT4:1;
unsigned BIT5:1;
unsigned BIT6:1;
unsigned BIT7:1;
unsigned BIT8:1;
unsigned BIT9:1;
unsigned BIT10:1;
unsigned BIT11:1;
unsigned BIT12:1;
unsigned BIT13:1;
unsigned BIT14:1;
unsigned BIT15:1;
};
# define VIRTUAL_BIT_COUNT 16
#endif
/*---------------------*
* 动 作 宏 定 义 *
*---------------------*/
#ifndef VRCK
# define VRCK _PB1
#endif
#ifndef VSCK
# define VSCK _PB2
#endif
#ifndef VSI
# define VSI _PB3
#endif
/***********************
* 全局变量声明区 *
***********************/
#if (VIRTUAL_BIT_COUNT == 8)
char VPORT = 0;
# define PV0 (*VPORTBit).BIT0
# define PV1 (*VPORTBit).BIT1
# define PV2 (*VPORTBit).BIT2
# define PV3 (*VPORTBit).BIT3
# define PV4 (*VPORTBit).BIT4
# define PV5 (*VPORTBit).BIT5
# define PV6 (*VPORTBit).BIT6
# define PV7 (*VPORTBit).BIT7
#endif
#if (VIRTUAL_BIT_COUNT == 16)
unsigned int VPORT = 0;
# define PV0 (*VPORTBit).BIT0
# define PV1 (*VPORTBit).BIT1
# define PV2 (*VPORTBit).BIT2
# define PV3 (*VPORTBit).BIT3
# define PV4 (*VPORTBit).BIT4
# define PV5 (*VPORTBit).BIT5
# define PV6 (*VPORTBit).BIT6
# define PV7 (*VPORTBit).BIT7
# define PV8 (*VPORTBit).BIT8
# define PV9 (*VPORTBit).BIT9
# define PV10 (*VPORTBit).BIT10
# define PV11 (*VPORTBit).BIT11
# define PV12 (*VPORTBit).BIT12
# define PV13 (*VPORTBit).BIT13
# define PV14 (*VPORTBit).BIT14
# define PV15 (*VPORTBit).BIT15
#endif
struct VirtualPORT *VPORTBit = (struct VirtualPORT *)&(VPORT);
char IfPortChange = False;
/***********************
* 系统函数声明区 *
***********************/
void refreshVirtualPORT(void);
void sendBITS(char Data);
void VirtualPORTProccess(void);
char setBIT(char BIT);
char clearBIT(char BIT);
/********************************************************
*函数说明:虚拟端口置位函数 *
*输入: 位编号 *
*输出: 操作是否成功 *
********************************************************/
char setBIT(char BIT)
{
if (BIT >= VIRTUAL_BIT_COUNT)
{
return False;
}
VPORT |= 1<<BIT;
IfPortChange = True;
VirtualPORTProccess(); //刷新端口
return True;
}
/********************************************************
*函数说明:虚拟端口清零函数 *
*输入: 位编号 *
*输出: 操作是否成功 *
********************************************************/
char clearBIT(char BIT)
{
if (BIT >= VIRTUAL_BIT_COUNT)
{
return False;
}
VPORT &= ~(1<<BIT);
IfPortChange = True;
VirtualPORTProccess(); //刷新端口
return True;
}
/********************************************************
*函数说明:虚拟端口处理程序 *
********************************************************/
void VirtualPORTProccess(void)
{
if (IfPortChange)
{
refreshVirtualPORT();
IfPortChange = False;
}
}
/********************************************************
*函数说明:刷新虚拟端口函数 *
********************************************************/
void refreshVirtualPORT(void)
{
char n = 0;
char TempData = 0;
VRCK = 0;
for (n=0;n<(VIRTUAL_BIT_COUNT>>3);n++)
{
TempData = (VPORT<<(n<<3))>>(VIRTUAL_BIT_COUNT-8);
sendBITS(TempData);
}
VRCK = 1;
IfPortChange = False;
}
/********************************************************
*函数说明:发送串行数据函数 *
*输入: 要发送的字节 *
********************************************************/
void sendBITS(char Data)
{
char n = 0;
for (n = 0;n<8;n++)
{
VSCK = 0;
if (((Data<<n)& 0x80 )==0)
{
VSI = 0;
}
else
{
VSI = 1;
}
VSCK = 1; //拉高时钟线
//下降沿锁存
}
}
#endif 以上头文件主要由三部分组成
1、虚拟端口的数据结构定义 也就是 位段的定义部分。该部分用来描述虚拟端口的规模,并且定义了虚拟端口变量,通过地址邦定,实现对虚拟端口位操作的支持。
2、基本操作函数。他们分别是:
void sendBITS(char Data) 发送数据到595
void refreshVirtualPORT(void) 刷新端口
3、辅助函数
他们是一组基于扫描刷新思想的函数,其实可以忽略的。
分别是:
char setBIT(char BIT) 指定虚拟端口置位函数(自动刷新)
char clearBIT(char BIT) 指定虚拟端口置零函数(自动刷新)
void VirtualPORTProccess(void) 扫描刷新函数,当端口变化标志变量被置位时,刷新端口。 之前也有這樣的想法,但只從用了3310液晶後, 其他的液晶都打入冷宮了. 呵呵,驱动1602只是SerialToCollateral.h头文件的一个范例。
我的目的是通过这种方法,使用3根线,就产生若干的虚拟端口(目前至少可以达到32个)。
这样可以驱动好多只输出的对速度要求不是那么严格的设备哦! 为楼主的无私奉献喝彩 给楼主一个建议,spi接口加cs脚加595,可能会更好点。 这个头文件的好处是,不需要使用硬件SPI
任意端口都可以连接595 打个纪号.以后可以用.做PLC应该有点用吧.控制继电器不错呢. 拿下做试验!!
谢谢楼主的无私奉献!好人有好报! 我用ARM做毕业设计的,看看我能不能把它改成ARM的,只是到现在6线接法LCD还无法显示啊! 你用的是什么ARM呢?
如果是LPC213x我这里有一个位操作的头文件,用这个头文件以后,你几乎可以直接移植上面的头文件了。
#ifndef __Use_RD_LPC213X_H_
#define __Use_RD_LPC213X_H_
/**************************************************************
*函数库说明:ARM LPC213x系列操作辅助函数库 *
*版本: v1.0 *
*平台: LPC213X系列 *
*作者: 傻孩子 *
*日期: 2006年3月30日 *
*修改: 傻孩子 *
*修改日期:2006年3月30日 *
* *
*[说明] *
* 1、支持端口位操作。 *
**************************************************************/
# include "LPC2294.h"
/************************
* 结 构 体 定 义 *
************************/
/*----------------------*
* 8位变量位映射 *
*----------------------*/
typedef struct BYTE_BIT
{
unsigned BIT0:1;
unsigned BIT1:1;
unsigned BIT2:1;
unsigned BIT3:1;
unsigned BIT4:1;
unsigned BIT5:1;
unsigned BIT6:1;
unsigned BIT7:1;
}BYTEBIT;
/*----------------------*
* 16位变量位映射 *
*----------------------*/
typedef struct WORD_BIT
{
unsigned BIT0:1;
unsigned BIT1:1;
unsigned BIT2:1;
unsigned BIT3:1;
unsigned BIT4:1;
unsigned BIT5:1;
unsigned BIT6:1;
unsigned BIT7:1;
unsigned BIT8:1;
unsigned BIT9:1;
unsigned BIT10:1;
unsigned BIT11:1;
unsigned BIT12:1;
unsigned BIT13:1;
unsigned BIT14:1;
unsigned BIT15:1;
}WORDBIT;
/*----------------------*
* 32位变量位映射 *
*----------------------*/
typedef struct DWORD_BIT
{
unsigned BIT0:1;
unsigned BIT1:1;
unsigned BIT2:1;
unsigned BIT3:1;
unsigned BIT4:1;
unsigned BIT5:1;
unsigned BIT6:1;
unsigned BIT7:1;
unsigned BIT8:1;
unsigned BIT9:1;
unsigned BIT10:1;
unsigned BIT11:1;
unsigned BIT12:1;
unsigned BIT13:1;
unsigned BIT14:1;
unsigned BIT15:1;
unsigned BIT16:1;
unsigned BIT17:1;
unsigned BIT18:1;
unsigned BIT19:1;
unsigned BIT20:1;
unsigned BIT21:1;
unsigned BIT22:1;
unsigned BIT23:1;
unsigned BIT24:1;
unsigned BIT25:1;
unsigned BIT26:1;
unsigned BIT27:1;
unsigned BIT28:1;
unsigned BIT29:1;
unsigned BIT30:1;
unsigned BIT31:1;
}DWORDBIT;
/*----------------------*
* 32位变量4分映射 *
*----------------------*/
typedef struct DWORD_DIV4
{
unsigned BYTEA:8;
unsigned BYTEB:8;
unsigned BYTEC:8;
unsigned BYTED:8;
}DWORDPORT8;
typedef struct DWORD_DIV2
{
unsigned WORDA:16;
unsigned WORDB:16;
}DWORDPORT16;
/*----------------------*
* 16位变量2分映射 *
*----------------------*/
typedef struct WORD_DIV2
{
unsigned BYTEA:8;
unsigned BYTEB:8;
}WORDPORT8;
/*----------------------*
* 8位变量2分映射 *
*----------------------*/
typedef struct BYTE_DIV2
{
unsigned BYTEL:4;
unsigned BYTEH:4;
}WORDHBYTE;
/************************
* 系 统 宏 定 义 *
************************/
/*----------------------*
* 系统常数宏定义 *
*----------------------*/
/************************
* 动 作 宏 定 义 *
************************/
# define P0 (*((volatile DWORDBIT *)0xE0028000))
# define DIR0(*((volatile DWORDBIT *)0xE0028008))
# define P1 (*((volatile DWORDBIT *)0xE0028010))
# define DIR1(*((volatile DWORDBIT *)0xE0028018))
# define PORT0 (*((volatile DWORDPORT8 *)0xE0028000))
# define PORT1 (*((volatile DWORDPORT8 *)0xE0028010))
# define WPORT0 (*((volatile DWORDPORT16 *)0xE0028000))
# define WPORT1 (*((volatile DWORDPORT16 *)0xE0028010))
# define PORT0A PORT0.BYTEA
# define PORT0B PORT0.BYTEB
# define PORT0C PORT0.BYTEC
# define PORT0D PORT0.BYTED
# define PORT1A PORT1.BYTEA
# define PORT1B PORT1.BYTEB
# define PORT1C PORT1.BYTEC
# define PORT1D PORT1.BYTED
# define WPORTA WPORT0.WORDA
# define WPORTB WPORT0.WORDB
# define WPORTC WPORT1.WORDA
# define WPORTD WPORT1.WORDB
# define P00 P0.BIT0
# define P01 P0.BIT1
# define P02 P0.BIT2
# define P03 P0.BIT3
# define P04 P0.BIT4
# define P05 P0.BIT5
# define P06 P0.BIT6
# define P07 P0.BIT7
# define P08 P0.BIT8
# define P09 P0.BIT9
# define P010 P0.BIT10
# define P011 P0.BIT11
# define P012 P0.BIT12
# define P013 P0.BIT13
# define P014 P0.BIT14
# define P015 P0.BIT15
# define P016 P0.BIT16
# define P017 P0.BIT17
# define P018 P0.BIT18
# define P019 P0.BIT19
# define P020 P0.BIT20
# define P021 P0.BIT21
# define P022 P0.BIT22
# define P023 P0.BIT23
# define P024 P0.BIT24
# define P025 P0.BIT25
# define P026 P0.BIT26
# define P027 P0.BIT27
# define P028 P0.BIT28
# define P029 P0.BIT29
# define P030 P0.BIT30
# define P031 P0.BIT31
# define P10 P1.BIT0
# define P11 P1.BIT1
# define P12 P1.BIT2
# define P13 P1.BIT3
# define P14 P1.BIT4
# define P15 P1.BIT5
# define P16 P1.BIT6
# define P17 P1.BIT7
# define P18 P1.BIT8
# define P19 P1.BIT9
# define P110 P1.BIT10
# define P111 P1.BIT11
# define P112 P1.BIT12
# define P113 P1.BIT13
# define P114 P1.BIT14
# define P115 P1.BIT15
# define P116 P1.BIT16
# define P117 P1.BIT17
# define P118 P1.BIT18
# define P119 P1.BIT19
# define P120 P1.BIT20
# define P121 P1.BIT21
# define P122 P1.BIT22
# define P123 P1.BIT23
# define P124 P1.BIT24
# define P125 P1.BIT25
# define P126 P1.BIT26
# define P127 P1.BIT27
# define P128 P1.BIT28
# define P129 P1.BIT29
# define P130 P1.BIT30
# define P131 P1.BIT31
# define DIR00 DIR0.BIT0
# define DIR01 DIR0.BIT1
# define DIR02 DIR0.BIT2
# define DIR03 DIR0.BIT3
# define DIR04 DIR0.BIT4
# define DIR05 DIR0.BIT5
# define DIR06 DIR0.BIT6
# define DIR07 DIR0.BIT7
# define DIR08 DIR0.BIT8
# define DIR09 DIR0.BIT9
# define DIR010 DIR0.BIT10
# define DIR011 DIR0.BIT11
# define DIR012 DIR0.BIT12
# define DIR013 DIR0.BIT13
# define DIR014 DIR0.BIT14
# define DIR015 DIR0.BIT15
# define DIR016 DIR0.BIT16
# define DIR017 DIR0.BIT17
# define DIR018 DIR0.BIT18
# define DIR019 DIR0.BIT19
# define DIR020 DIR0.BIT20
# define DIR021 DIR0.BIT21
# define DIR022 DIR0.BIT22
# define DIR023 DIR0.BIT23
# define DIR024 DIR0.BIT24
# define DIR025 DIR0.BIT25
# define DIR026 DIR0.BIT26
# define DIR027 DIR0.BIT27
# define DIR028 DIR0.BIT28
# define DIR029 DIR0.BIT29
# define DIR030 DIR0.BIT30
# define DIR031 DIR0.BIT31
# define DIR10 DIR1.BIT0
# define DIR11 DIR1.BIT1
# define DIR12 DIR1.BIT2
# define DIR13 DIR1.BIT3
# define DIR14 DIR1.BIT4
# define DIR15 DIR1.BIT5
# define DIR16 DIR1.BIT6
# define DIR17 DIR1.BIT7
# define DIR18 DIR1.BIT8
# define DIR19 DIR1.BIT9
# define DIR110 DIR1.BIT10
# define DIR111 DIR1.BIT11
# define DIR112 DIR1.BIT12
# define DIR113 DIR1.BIT13
# define DIR114 DIR1.BIT14
# define DIR115 DIR1.BIT15
# define DIR116 DIR1.BIT16
# define DIR117 DIR1.BIT17
# define DIR118 DIR1.BIT18
# define DIR119 DIR1.BIT19
# define DIR120 DIR1.BIT20
# define DIR121 DIR1.BIT21
# define DIR122 DIR1.BIT22
# define DIR123 DIR1.BIT23
# define DIR124 DIR1.BIT24
# define DIR125 DIR1.BIT25
# define DIR126 DIR1.BIT26
# define DIR127 DIR1.BIT27
# define DIR128 DIR1.BIT28
# define DIR129 DIR1.BIT29
# define DIR130 DIR1.BIT30
# define DIR131 DIR1.BIT31
#endif
-----此内容被Gorgon Meducer于2006-05-15,08:30:43编辑过 我现在要用M16做液晶显示,IO口不够,正好遇到楼主的595级联可以剩下不少IO口。
但是,我按楼主说的连线仿真试了一下,1602的这个没有图象,而12864的那个出来的是乱码。。。。请楼主指教,谢谢。 等待 现在12864程序显示的是只有液晶的上面一条,可以看出来是楼主的签名文字。而1602出现的是乱码,总是调不好。请楼主指点一下!估计是延时和时序的问题,我用M16,7.3728M晶振。 请问楼主,我现在把1602的程序调到能正常显示字符,但是问题是它不能换行,列数也不是按着预定的位置显示。(我现在只让它显示不动字符串)。 还有就是比如输出字符串“OURAVR”,最后一个‘R’会没有显示,而如果在最后加个空格("OURAVR "),就可以完全显示出来 不错,收藏。谢谢楼主的共享 to:17楼,这情况我也遇到过!!前面加句,清屏就OK了!! 可以了。是要加清屏 主要原因可能在
void LCDWaitForReady(void)
函数中的延时等待上,如果出现无法显示的问题,请将该延时增大
例如
LCDDelayUs(300);
直到乱码变成正常显示为止。然后逐渐改小。这个直接和时钟主频有关系。我测试的时候,使用的是内部8M。 下载,正在学习中 放弃了,移植到cvavr上面难度太高。 自己写了一个cvavr上面的,一次成功,感觉比楼主的简单 这样的扩展方式是可以显示,但速度明显示的过慢了,因为不能读LCD的忙信号,使写入速度慢了很多,不打算这样扩展 io吃尽的状况下面明显很好 怎么收藏? mark 串转并 英文是 Serial to parallel convert
collateral 是 间接,连带 的意思,用在这里不好 mark to 【29楼】 kl818bc
谢谢你。 mark lz,关键部分的代码最好能有注释,这样好读一点。 那段 void refreshVirtualPORT(void) 我读了半个小时,才貌似读懂 struct VirtualPORT *VPORTBit = (struct VirtualPORT *)&(VPORT); 是什么意思啊。这一句的上面那一段是 位定义 吧,在程序中好像没用到啊 记号 谢谢Lz DING 顶,好想法 实践过 595 串并转换驱动24064的LCD, 不过是带字库的. 电路,电路,电路?? mark 学习 mark! mark! MARK,谢谢楼主 顶一个,傻孩子 mark...传说中的傻孩子。 MARK MARK! 跟plc扩展模块架构差不多 先留着 支持傻孩子 Gorgon_Meducer 发表于 2006-2-9 16:26 static/image/common/back.gif
以上头文件主要由三部分组成
1、虚拟端口的数据结构定义 也就是 位段的定义部分。该部分用来描述虚拟端口 ...
楼主在2006年就玩出这个了
很厉害的 果断学习了 IO不够的时候,这个是好方法啊,多谢LZ
页:
[1]