74HC595功能是将串行数据(由SHCP\CLK、DS\DATA输入串行数据)转换并行数据(芯片上的QA~QH八个数据输出口);
具体工作方式是:由CLK提供时钟,DATA输入高低电平(数据),CLK每输入一个上升沿,数据移位,当所有数据输入完成后,CS\STCP输入一个上升沿,将数据输出到8个输出口;
如果要使用多个HC595,只需将HC595的Q7S接入下一个HC595的DS\DATA, 提供相同的CLK,当然CS\STCP也相同(同时输出)。
分析如上时序图:
SI\DS\TATA 数据输入
SCK\SHCP\CLK 上升沿 移位寄存器移位
RCK\STCP\DS 上升沿 将移位寄存器中数据输出到8个口
OE 低电平输出使能(如果用HC595控制数码管、LED,可以将PWM输入OE以控制亮度)
SHCP\CLK即时钟信号,DS\DATA在一开始输入一段高电平,即输入1,在这段高电平中间,SHCP\CLK 输入了一个上升沿,所以会将1移入移位寄存器,因为在一开始MR\SCLR(低电平清零移位寄存器)输入了一段低电平,所以移入1后,此时移位寄存器应该是:1000 0000 ,再之后便是RCK\STCP\DS 输入了一个上升沿,将 移位寄存器 中的数据进入 存储寄存器 ,因为此时OE为低电平,所以会将 存储寄存器 中数据通过QA~QH 8个口输出,此时应该是QA为高电平,其他为低电平,即QA~QH:1000 0000。
然后RCK\STCP\DS 又输入了一个上升沿,所以应该是QB为高电平,其他为低电平,QA~QH: 0100 0000。以此类推。
直到输入了第8个上升沿QA~QH: 0000 0001
第9个上升沿: QA~QH: 0000 0000 Q2A~Q2H: 1000 0000
本次顺便学习了一下STM32CubeMX的使用,STM32CubeMX目前只支持HAL库和LL库,所以我的程序使用的是HAL库,一般学习初学STM32都是使用正点原子的板子和例程,使用的是标准库,所以不能直接copy(挺简单的自己重新写一下就行)。
程序:
#include "hc595.h"
#include "stm32f1xx_hal.h"
#define HC595_CLK_H() HAL_GPIO_WritePin(GPIOB, HC595_CLK_Pin, GPIO_PIN_SET)
#define HC595_CLK_L() HAL_GPIO_WritePin(GPIOB, HC595_CLK_Pin, GPIO_PIN_RESET)
#define HC595_DATA_H() HAL_GPIO_WritePin(GPIOB, HC595_DATA_Pin, GPIO_PIN_SET)
#define HC595_DATA_L() HAL_GPIO_WritePin(GPIOB, HC595_DATA_Pin, GPIO_PIN_RESET)
#define HC595_CS_H() HAL_GPIO_WritePin(GPIOB, HC595_CS_Pin, GPIO_PIN_SET)
#define HC595_CS_L() HAL_GPIO_WritePin(GPIOB, HC595_CS_Pin, GPIO_PIN_RESET)
#define HC595_CLK_UP() HC595_CLK_L();\
__NOP();\
HC595_CLK_H()
#define HC595_CS_UP() HC595_CS_L();\
__NOP();\
HC595_CS_H()
/*
16 VCC 电源 2V-6V
15 QA 并行输出 QB QC QD
14 SI/DS DATA 串行数据输入
13 OE_ 输出使能 PWM控制亮度
12 RCK/STCP CS 输出到锁存器时钟
11 SCK/SHCP CLK DATA输入时钟
10 SCLR/MR 低电平清零 接VCC
9 SQH/Q7S 串行数据输出 接下一个595
*/
void HC595SendData(uint8_t data)
{
uint8_t j;
for (j = 0; j < 8; j++)
{
if(((data<<j) & 0x80) !=0)
HC595_DATA_H();
else
HC595_DATA_L();
HC595_CLK_UP();
}
//HC595Load();
}
void HC595Load(void)
{
HC595_CS_UP();
}
void LedRowOn(uint8_t Row7_0, uint8_t Row15_8, uint8_t Row16_23,uint8_t Row31_24)
{
HC595SendData(Row15_8);
HC595SendData(Row7_0);
HC595SendData(Row31_24);
HC595SendData(Row16_23);
HC595Load();
}
void LedRowOut(uint32_t Data)
{
// HC595SendData(Data >> 24);
//HC595SendData(Data >> 16);
HC595SendData(Data >> 8);
HC595SendData(Data >> 0);
HC595Load();
}
while(1) {
uint32_t val = 1;
for(int i=0; i<16; i++)
{
LedRowOut(val);
val <<= 1;
delay_ms(100);
}
}
结束。