电路图
使用了两个串转并芯片,一个74HC595,一个74HC164。
这两者的区别,一个有锁存功能,一个没有。移位8位后,需要对74HC595多做一个操作,RCLK引脚施加上升沿,实现锁存并输出。
74HC595和单片机通信使用3个引脚,11,12 ,14脚
74HC164和单片机通信使用2个引脚,1和2相连接,8脚
需要加限流电阻。
LED点阵电路图如下所示。
确定点阵的引脚。
我的点阵引脚总结如下:
咱不管行列,只看高低电平:
3 4 6 10 11 13 15 16接高电平,对应字库,接595,加330R限流电阻
序号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
对应引脚(焊接时候注意) | 13 | 3 | 4 | 10 | 6 | 11 | 15 | 16 |
1 2 5 7 8 9 12 14接低电平,每次依次拉低一个引脚,扫描作用。 接163
序号 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
对应引脚 | 9 | 14 | 8 | 12 | 1 | 7 | 2 | 5 |
实物图
通信引脚用杜邦线引出。
用了2节电池3V给点阵电路供电,电池的地要和单片机的地连接在一起。单片机的输出电压为3.3V。点阵电路的电压输入大于供电电压,需要注意输入钳位电流。
跳线焊接太累了,还是做PCB再焊吧。脖子都要断了。
流程图
主要代码
main.c
int main(void)
{
/* LED 端口初始化 */
_595_164_GPIO_Config();
//将595 164的控制引脚拉低
_595_RCK(LOW);
_595_SCK(LOW);
_164_SCK(LOW);
_74HC595_WriteByte(0x41);//74HC595写入0x48(0100 1000)
_74HC164_WriteByte(0x00);//所有列写低电平
unsigned char i;
unsigned char zimo_0[8] = {0x00 ,0x00 ,0x3E ,0x41 ,0x41 ,0x41 ,0x3E ,0x00};
while(1)
{
for(i=0;i<8;i++) //当i>8时,跳出循环,即次函数循环8次(8位移位寄存器)
{
_74HC595_WriteByte(zimo_0[i]);//74HC595写入0x48(0100 1000)
_74HC164_WriteByte((~0x80)>>i);//对此列写低电平,使得此列亮
delay_ms(3);//此列亮保持一会儿.一秒24帧以上,4ms以下
}
}
}
leds.h
#include "leds.h"
/**
* @brief 初始化控制LED的IO
* @param 无
* @retval 无
*/
void _595_164_GPIO_Config(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启LED相关的GPIO外设时钟*/
RCC_APB2PeriphClockCmd( _74HC595_RCC | _74HC164_RCC , ENABLE);
/*选择要控制的GPIO引脚*/
GPIO_InitStructure.GPIO_Pin = _74HC595_SERIAL_INPUT_PIN | _74HC595_SCK_PIN | _74HC595_RCK_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化GPIO*/
GPIO_Init(_74HC595_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = _74HC164_SERIAL_INPUT_PIN|_74HC164_SCK_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化GPIO*/
GPIO_Init(_74HC164_PORT, &GPIO_InitStructure);
}
//定义595需要输入的串行数据
void _74HC595_WriteByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++) //当i>8时,跳出循环,即次函数循环8次(8位移位寄存器)
{
_595_SERIAL_INPUT(Byte&(0x80>>i));//非0即1,每运行1次,数据整体右移一位 0x80=1000 0000b
_595_SCK(HIGH); //SCK上升沿时,DS的数据写入移位寄存器
_595_SCK(LOW);
// _595_RCK(HIGH); //RCK上升沿时,数据从移位寄存器转存储存寄存器
// _595_RCK(LOW);
}
_595_RCK(HIGH); //上升沿时,数据从移位寄存器转存储存寄存器
_595_RCK(LOW);
}
//定义164需要输入的串行数据
void _74HC164_WriteByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++) //当i>8时,跳出循环,即次函数循环8次(8位移位寄存器)
{
_164_SERIAL_INPUT(Byte&(0x80>>i));//非0即1,每运行1次,数据整体右移一位 0x80=1000 0000b
_164_SCK(HIGH); //SHCP上升沿时,DS的数据写入移位寄存器
_164_SCK(LOW);
}
}
leds.c
#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"
//开发板上的通信引脚
//PA4 595_SERIAL_INPUT
//PA5 SCK
//PA6 RCK
//PB12 164_SERIAL_INPUT
//PB13 SCK
#define _74HC595_PORT GPIOA /* GPIO端口 */
#define _74HC595_RCC RCC_APB2Periph_GPIOA
#define _74HC595_SERIAL_INPUT_PIN GPIO_Pin_4
#define _74HC595_SCK_PIN GPIO_Pin_5
#define _74HC595_RCK_PIN GPIO_Pin_6
#define _74HC164_PORT GPIOB /* GPIO端口 */
#define _74HC164_RCC RCC_APB2Periph_GPIOB
#define _74HC164_SERIAL_INPUT_PIN GPIO_Pin_12
#define _74HC164_SCK_PIN GPIO_Pin_13
/** the macro definition to trigger the led on or off
* 1 - off
*0 - on
*/
#define HIGH 1
#define LOW 0
/* 使用标准的固件库控制IO*/
#define _595_SERIAL_INPUT(a) if (a) \
GPIO_SetBits(_74HC595_PORT,_74HC595_SERIAL_INPUT_PIN);\
else \
GPIO_ResetBits(_74HC595_PORT,_74HC595_SERIAL_INPUT_PIN)
#define _595_SCK(a) if (a) \
GPIO_SetBits(_74HC595_PORT,_74HC595_SCK_PIN);\
else \
GPIO_ResetBits(_74HC595_PORT,_74HC595_SCK_PIN)
#define _595_RCK(a) if (a) \
GPIO_SetBits(_74HC595_PORT,_74HC595_RCK_PIN);\
else \
GPIO_ResetBits(_74HC595_PORT,_74HC595_RCK_PIN)
#define _164_SERIAL_INPUT(a) if (a) \
GPIO_SetBits(_74HC164_PORT,_74HC164_SERIAL_INPUT_PIN);\
else \
GPIO_ResetBits(_74HC164_PORT,_74HC164_SERIAL_INPUT_PIN)
#define _164_SCK(a) if (a) \
GPIO_SetBits(_74HC164_PORT,_74HC164_SCK_PIN);\
else \
GPIO_ResetBits(_74HC164_PORT,_74HC164_SCK_PIN)
void _595_164_GPIO_Config(void);
void _74HC595_WriteByte(unsigned char Byte);
void _74HC164_WriteByte(unsigned char Byte);
#endif /* __LED_H */