在嵌入式设计中,微控制器中存在没有足够的I/O引脚的可能性。这可能是由于任何原因造成的,可能是您的应用程序需要多个 LED,或者您想使用多个 7 段显示器,但您的微控制器中没有所需的 I/O 引脚。这里有一个完美的组件,移位寄存器。移位寄存器接受串行数据并提供并行输出。它只需要3 个引脚即可与您的微控制器连接,您将从中获得超过 8 个输出引脚。其中一个流行的移位寄存器是74HC595。它具有8位存储寄存器和8位移位寄存器。
您将向移位寄存器提供串行数据,该数据将被锁存于存储寄存器上,然后存储寄存器将控制 8 个输出。如果您想要更多输出,只需添加另一个移位寄存器。通过级联两个移位寄存器,您将获得额外的 8 个输出,总共 16 位输出。
移位寄存器 74HC595:
这是根据数据表的74HC595的引脚图-
HC595 有 16 针;如果我们看到数据表,我们将了解引脚功能-
QA至QH,从引脚号1到7和15用作移位寄存器的8位输出,其中引脚14用于接收串行数据。还有关于如何使用其他引脚和利用移位寄存器的其他功能的真值表。
当我们编写用于连接74HC595的代码时,我们将应用此真值表来获取所需的输出。
所需组件:
PIC16F877A
2个33pF陶瓷盘式电容器
20兆赫晶体
4.7k 电阻
8颗发光二极管
1k 电阻器 -1 个(如果需要每个 LED 上的单独电阻器,则需要 8 个 1k 电阻器)
74HC595 集成电路
5V墙上适配器
PIC 编程环境
面包板和电线
电路图:
在电路图中,我们连接了串行数据引脚;时钟和选通(锁存)引脚分别位于微控制器的RB0,RB1和RB2引脚上。在这里,我们使用一个电阻器用于8个LED。根据真值表,我们通过将74HC595的引脚13接地来启用输出。QH引脚保持打开状态,因为我们不会用它级联另一个74HC595。我们通过将移位寄存器的引脚10与VCC连接来禁用清除输入标志。
晶体振荡器连接在微控制器的 OSC 引脚上。PIC16F877A 没有任何内部振荡器。在本项目中,我们将使用移位注册表从 Q0 到 Q7逐个点亮 lead。
我们在面包板中构建了电路-
代码说明:
文末给出了使用移位寄存器控制LED的完整代码。与往常一样,我们需要在PIC微控制器中设置配置位。
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
之后,我们声明了延迟所需的晶体频率和74HC595的引脚声明。
#include
/*
Hardware related definition
*/
#define _XTAL_FREQ 20000000 //Crystal Frequency, used in delay
#define DATA_595 PORTBbits.RB0
#define STROBE_595 PORTBbits.RB1
#define CLK_595 PORTBbits.RB2
接下来我们声明了 system_init() 函数来初始化引脚方向。
void system_init(void){
TRISB = 0x00;
}
我们使用两种不同的函数创建了时钟脉冲和锁存脉冲
/*
*This function will enable the Clock.
*/
void clock(void){
CLK_595 = 1;
__delay_us(500);
CLK_595 = 0;
__delay_us(500);
}
和
/*
*This function will strobe and enable the output trigger.
*/
void strobe(void){
STROBE_595 = 1;
__delay_us(500);
STROBE_595 = 0;
}
在这两个函数之后,我们声明了data_submit(无符号 int data)函数以向74HC595提交串行数据。
void data_submit(unsigned int data){
for (int i=0 ; i<8 ; i++){
DATA_595 = (data >> i) & 0x01;
clock();
}
strobe(); // Data finally submitted
}
在此函数中,我们接受 8 位数据并使用两个按位运算符左移和AND运算符发送每个位。我们首先逐个移动数据,并使用带有 0x01 的 AND 运算符找出确切的位是 0 还是 1。每个数据都由时钟脉冲存储,最终数据输出使用锁存器或选通脉冲完成。在此过程中,数据输出将首先是MSB(最高有效位)。
在主函数中,我们提交了二进制文件,并逐个将输出引脚调高。
system_init(); // System getting ready
while(1){
data_submit(0b00000000);
__delay_ms(200);
data_submit(0b10000000);
__delay_ms(200);
data_submit(0b01000000);
__delay_ms(200);
data_submit(0b00100000);
__delay_ms(200);
data_submit(0b00010000);
__delay_ms(200);
data_submit(0b00001000);
__delay_ms(200);
data_submit(0b00000100);
__delay_ms(200);
data_submit(0b00000010);
__delay_ms(200);
data_submit(0b00000001);
__delay_ms(200);
data_submit(0xFF);
__delay_ms(200);
}
return;
}
这就是移位寄存器可用于在任何微控制器中获得更多空闲I/O引脚以连接更多传感器的方式。
全部0条评论
快来发表一下你的评论吧 !