
以下为.h文件:
#ifndef __74HC595_H__
#define __74HC595_H__
#include "stm32f10x.h" #define SHCP_GPIO_PORT GPIOA
#define SHCP_GPIO_CLK RCC_APB2Periph_GPIOA
#define SHCP_GPIO_PIN GPIO_Pin_1 #define STCP_GPIO_PORT GPIOA
#define STCP_GPIO_CLK RCC_APB2Periph_GPIOA
#define STCP_GPIO_PIN GPIO_Pin_0 #define DS_GPIO_PORT GPIOB
#define DS_GPIO_CLK RCC_APB2Periph_GPIOB
#define DS_GPIO_PIN GPIO_Pin_1 #define HC595_SHCP_Low() GPIO_ResetBits( SHCP_GPIO_PORT, SHCP_GPIO_PIN )
#define HC595_SHCP_High() GPIO_SetBits( SHCP_GPIO_PORT, SHCP_GPIO_PIN )
#define HC595_STCP_Low() GPIO_ResetBits( STCP_GPIO_PORT, STCP_GPIO_PIN )
#define HC595_STCP_High() GPIO_SetBits( STCP_GPIO_PORT, STCP_GPIO_PIN )
#define HC595_Data_Low() GPIO_ResetBits( DS_GPIO_PORT, DS_GPIO_PIN )
#define HC595_Data_High() GPIO_SetBits( DS_GPIO_PORT, DS_GPIO_PIN )void HC595_GPIO_Config(void);
void HC595_Send_Byte(u8 byte);
void HC595_CS(void);
void HC595_Send_Multi_Byte(u8 *data, u16 len);#endif
以下为.c文件:
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"#include "74HC595.h"
void delay(uint16_t t);/******** 74HC595 GPIO 配置 *************************/
void HC595_GPIO_Config(void)
{ GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd( SHCP_GPIO_CLK | STCP_GPIO_CLK | DS_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = SHCP_GPIO_PIN;GPIO_Init(SHCP_GPIO_PORT, &GPIO_InitStructure); // 初始化 SHCP 引脚GPIO_InitStructure.GPIO_Pin = STCP_GPIO_PIN;GPIO_Init(STCP_GPIO_PORT, &GPIO_InitStructure); // 初始化 STCP 引脚GPIO_InitStructure.GPIO_Pin = DS_GPIO_PIN;GPIO_Init(DS_GPIO_PORT, &GPIO_InitStructure); // 初始化 DS 引脚GPIO_ResetBits(SHCP_GPIO_PORT, SHCP_GPIO_PIN); // 引脚初始状态为高,便于产生上升沿GPIO_ResetBits(STCP_GPIO_PORT, STCP_GPIO_PIN); GPIO_ResetBits(DS_GPIO_PORT, DS_GPIO_PIN);
}/****74HC595 发送一个字节 *即往74HC595的DS引脚发送一个字节
*/
void HC595_Send_Byte(u8 byte)
{u8 i;for (i = 0; i < 8; i ++) //一个字节8位,传输8次,一次一位,循环8次,刚好移完8位{/**** 步骤1:将数据传到DS引脚 ****/if (byte & 0x80) //先传输高位,通过与运算判断第八是否为1HC595_Data_High(); //如果第八位是1,则与 595 DS连接的引脚输出高电平else //否则输出低电平HC595_Data_Low();/*** 步骤2:SHCP每产生一个上升沿,当前的bit就被送入移位寄存器 ***/HC595_SHCP_Low(); // SHCP拉低delay(1); // 适当延时HC595_SHCP_High(); // SHCP拉高, SHCP产生上升沿delay(1);byte <<= 1; // 左移一位,将低位往高位移,通过 if (byte & 0x80)判断低位是否为1}
}/***74HC595输出锁存 使能
**/
void HC595_CS(void)
{/** 步骤3:STCP产生一个上升沿,移位寄存器的数据移入存储寄存器 **/HC595_STCP_Low(); // 将STCP拉低delay(1); // 适当延时HC595_STCP_High(); // 再将STCP拉高,STCP即可产生一个上升沿delay(1);
}/***发送多个字节*便于级联时数据的发送*级联N级,就需要发送N个字节控制HC595
***/
void HC595_Send_Multi_Byte(u8 *data, u16 len)
{u8 i;for (i = 0; i < len; i ++ ) // len 个字节{HC595_Send_Byte(data[i]);}HC595_CS(); //先把所有字节发送完,再使能输出
}void delay(uint16_t t)
{for (; t != 0; t --);}
关于HC595_Send_Multi_Byte函数的使用要根据实际的硬件情况来,以下为一个例子,可以参考一下:

程序中的相关数据:
u8 Led_Buf[2] = {0xff, 0xff}; //存储要发送的指令字节,也就是灯的状态 Led_Buf[0]控制灯6-10;Led_Buf[1]控制灯1-5
u8 Led_All_Off[2] = {0xff, 0xff}; //LED灯全灭
u8 Led_All_On[2] = {0x00, 0x00}; //LED灯全亮HC595_Send_Multi_Byte(Led_All_On,2);//10路灯全开
HC595_Send_Multi_Byte(Led_All_Off,2);//10路灯全关
实现流水灯效果:
/****************************************************** *流水灯程序
*******************************************************/
void LED_ShowOneToOne(void)
{u8 pos; // led位置 u8 Led_Show[2] = {0xff, 0xff}; //存储要发送的指令字节, Led_Show[0]控制灯6-10; Led_Show[1]控制灯1-5//第X个led亮 :1 2 3 4 5 u8 Waterfall_Led[20] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, //控制第一级74HC5950xff, 0xff, 0xff, 0xff, 0xff, //第X个led亮 :6 7 8 9 10 0xff, 0xff, 0xff, 0xff, 0xff, //控制第二级74HC5950xfe, 0xfd, 0xfb, 0xf7, 0xef };for (pos = 0; pos < 10; pos ++) //第pos个灯,实现流水灯效果{ Led_Show[1] = Waterfall_Led[pos]; //存放第一级74HC595数据,因为先进先出,所以第一级放在Led_Pos_Buf[1],而不是Led_Pos_Buf[0]Led_Show[0] = Waterfall_Led[pos+10]; //存放第二级74HC595的数据 HC595_Send_Multi_Byte(Led_Show,2); //将当前数据发送到595 delay_ms(500); }
}















