I always found it difficult to understand when I first learned about single-chip microcomputers. Today, I analyze the 74HC595 serial port to parallel port IO expansion chip. Generally, we can only use this artifact when the IO port is not enough. So how do we drive this artifact? "Read Mantra: Heavenly and Earthly, Q1 open"!
The product manual will not be posted, and the articles that can be seen are all driven by the driver.
Concept carding
SI serial data input == equivalent to the water 0 or 1 above
SCK shift register clock, rising edge shift == equivalent to the internal piston above
RCK latch register clock, rising edge storage == equivalent to removing the water storage tank
driver writing
The first step is to put down the water storage tank RCK = 0;
The second step is to press the piston down SCK =0;
In the third step, the water is pressed to the water storage tank SI = 0 or SI = 1 through the water outlet;
The fourth step is to lift the piston up SCK =1;
Cycle 8 times to fill the storage tank with water
The fifth step is to lift the storage tank RCK =1;
Does the image belong to the understanding that 8 times of water is equivalent to 8 data 0 or 1, for the output, it is the Q1-Q7 level state
code
#include "drvs.h"
// 74HC595 驱动
//资料 PB05 SI
//大平台 PB08 RCK
//活塞 PB09 SCK
//Q0 运行灯 Q1通讯灯 Q2故障灯 Q3过载灯 Q4 短路灯 Q5报警灯
#define SI_PORT (PortB)
#define SI_PIN (Pin05)
#define RCK_PORT (PortB)
#define RCK_PIN (Pin08)
#define SCK_PORT (PortB)
#define SCK_PIN (Pin09)
#define SI_ON() PORT_SetBits(SI_PORT,SI_PIN) //开1
#define SI_OFF() PORT_ResetBits(SI_PORT,SI_PIN) //关0
#define RCK_ON() PORT_SetBits(RCK_PORT,RCK_PIN) //开1
#define RCK_OFF() PORT_ResetBits(RCK_PORT,RCK_PIN) //关0
#define SCK_ON() PORT_SetBits(SCK_PORT,SCK_PIN) //开1
#define SCK_OFF() PORT_ResetBits(SCK_PORT,SCK_PIN) //关0
void Init_74HC595(void)
{
stc_port_init_t stcPortInit;
/*配置结构初始化*/
MEM_ZERO_STRUCT(stcPortInit);
stcPortInit.enPinMode = Pin_Mode_Out;//输出模式
stcPortInit.enExInt = Enable;//Enable//Disable
stcPortInit.enPullUp = Enable;//enPinDrv
/* BL10 Port/Pin 初始化 */
PORT_Init(SI_PORT, SI_PIN, &stcPortInit);
PORT_Init(RCK_PORT, RCK_PIN, &stcPortInit);
PORT_Init(SCK_PORT, SCK_PIN, &stcPortInit);
SI_OFF();//SI串行数据输入端
RCK_OFF();//RCK 锁存寄存器时钟,上升沿存储
SCK_OFF();//SCK 移位寄存器时钟,上升沿移位
}
//设置74HC595 端口电平
void Set_Show(uint8_t outdata)
{
RCK_OFF();//
uint8_t i;
for(i=0;i<8;i++)
{
SCK_OFF(); //
if(outdata&0x80)
{
SI_ON();//
}
else
{
SI_OFF();//
}
SCK_ON(); //
outdata<<=1;
}
RCK_ON(); //
}
uint8_t temp595=0xFF;//默认高电平灯全关
uint8_t tempces=0xFF;
//74HC595单独控制驱动
typedef enum
{
LED1, //Q0 LED1 运行灯
LED2, //Q1 LED2 通信灯
LED3, //Q2 LED3 故障灯
LED4, //Q3 LED4 过载灯
LED5, //Q4 LED5 短路灯
LED6, //Q5 LED6 报警灯
BUZZ, //Q6 蜂鸣器
BLED, //Q7 背光
LED_ALL, //全部启动
}IO74HC595;
/*
* com 某位端口
* val 电平值
*/
//控制595输出
void Set_IO_input(uint8_t com,uint8_t val)
{
if(com==LED_ALL)
{
if(val==0)//输入关
{
temp595=0xFF;//
}
else
{
temp595=0x00;
}
}
else
{
if(val==0)//输入关
{
temp595|=0x01<<com; //把某位置高电平
}
else //输入开
{
temp595 &= ~(0x01<<com);
}
}
if(tempces!=temp595)//数据变化才发送控制
{
tempces = temp595;
Set_Show(tempces);
}
}
//74HC595测试代码
void CS_74HC595(void)
{
Set_IO_input(LED1,1);//点亮LED1
}