STM32F103C8T6//74HC595//双数码管显示
.
.
本次要说明的程序
本程序是在cubemx初始化stm32f103c8后直接生成的初始程序上继续编程。
#include "main.h"
#define SDI_SET HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET)
#define SDI_RESET HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET)
#define SCLK_SET HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET)
#define SCLK_RESET HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET)
#define LOAD_SET HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET)
#define LOAD_RESET HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET)
uint32_t NumShow[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
void Delay1000ms();
void Show(uint32_t shi,uint32_t ge);
void delay(uint16_t temp)
{
uint16_t i,j,t;
t=temp;
while(t!=0)
{
for(i=200;i>0;i--)
for(j=248;j>0;j--);
t--;
}
}
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
int main(void)
{
uint32_t shi,ge;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (1)
{
for(shi=0;shi<10;shi++)
{
for(ge=0;ge<10;ge++)
{
Show(NumShow[shi],NumShow[ge]);
if (ge==10)
ge=0;
Delay1000ms();
if (ge%2==1)
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
else
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
}
if (shi==10)
shi=0;
}
}
}
void Show(uint32_t shi,uint32_t ge) //因为是两个74HC595的级联,所以先移位个位数,再移位十位数。这样才可显示(十位数,个位数)
{
uint32_t k,i;
for(k=0;k<8;k++) //下面的代码要循环8次,直到把整个数据的所有二进制数位遍历一遍
{
SCLK_RESET; //数据移位信号先为低电平,为移位准备
if((ge&0x80)==0x80) //如果所给的ge数据的二进制形式的最高位和0x80(10000000)相与后值不变,即最高位是1
{
SDI_SET; //判断出该数据的最高位是1,将该数据的最高位1送入移位寄存器
}
else //如果不是的话
SDI_RESET ; //判断出该数据的最高位是0,将该数据最高位的0送入移位寄存器
ge= ge<<1; //让ge的二进制数据整个左移一位,为下一次判断次高位做准备
SCLK_SET ; //让数据寄存器中的数据移位(Q0->Q1->Q2–>Q3–>…–>Q7)
}
LOAD_RESET ; //先确认拉低
LOAD_SET; //上升沿时移位寄存器的数据进入数据存储寄存器,ST_CP端产生一个正脉冲,更新显示数据
for(i=0;i<8;i++)
{
SCLK_RESET;
if((shi&0x80)==0x80)
{
SDI_SET;
}
else
SDI_RESET ;
shi=shi<<1;
SCLK_SET ;
}
LOAD_RESET ;
LOAD_SET;
}
void Delay1000ms() //@30.000MHz
{
unsigned char i, j, k;
i = 114;
j = 255;
k = 107;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
.
.
.
.
.
效果描述
程序实现数码管从00-99循环显示,每个数之间间隔1s左右
最终实现效果
图1
图2
.
.
.
.
硬件方面
核心板原理图
74hc595显示屏驱动芯片
74595的数据端说明 | |
---|---|
Q0–Q7 | 八位并行输出端,可以直接控制数码管的8个段 |
Q7’ | 级联输出端。将它接下一个595的DS端 |
DS | 串行数据输入端,级联的话接上一级的Q7’ |
74595的控制端说明 | |
(MR)’(10脚) | 低电平时将移位寄存器的数据清零。通常接到VCC防止数据清零 |
SH_CP(11脚) | 上升沿时数据寄存器的数据移位。Q0->Q1->Q2–>Q3–>…–>Q7;下降沿移位寄存器数据不变。(脉冲宽度:5V时,大于几十纳秒就行了。通常都选微秒级) |
ST_CP(12脚) | 上升沿时移位寄存器的数据进入数据存储寄存器,下降沿时存储寄存器数据不变。通常将ST_CP置为低电平,当移位结束后,在ST_CP端产生一个正脉冲(5V时,大于几十纳秒就行了。通常都选微秒级),更新显示数据。 |
(OE)’(13脚) | 高电平时禁止输出(高阻态)。如果单片机的引脚不紧张,用一个引脚控制它,可以方便地产生闪烁和熄灭效果。比通过数据端移位控制要省时省力。 |
补充:
1> 74595的主要优点是具有数据存储寄存器,在移位的过程中,输出端的数据可以保持不变。这在串行速度慢的场合很有用处,数码管没有闪烁感。
2> 595是串入并出带有锁存功能移位寄存器,它的使用方法很简单,如下面的真值表,在正常使用时ST_CP为低电平,/OE为低电平。从DS每输入一位数据,串行输入时钟SH_CP上升沿有效一次,直到八位数据输入完毕,输出时钟ST_CP上升沿有效一次,此时,输入的数据就被送到了输出端。
.
.
.
.
.
双数码管模块
介绍
外观尺寸
电路连接图
硬件中:
核心板---->PCB------>74HC595
B3--------->SDI------->DS(串行数据输入)
B4--------->SCL------>SH_CP(数据输入时钟线)
B5--------->LOAD---->ST_CP(数据输出时钟线)
C13--------------------->核心板上的灯
.
.
.
程序疑难讲解
#define SDI_SET HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET)
SDI高电平,
#define SDI_RESET HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET)
SDI低电平
串行数据输入
#define SCLK_SET HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET)
#define SCLK_RESET HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET)
SCLK上升沿时数据寄存器的数据移位。Q0->Q1->Q2–>Q3–>…–>Q7;下降沿移位寄存器数据不变。
#define LOAD_SET HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET)
#define LOAD_RESET HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET)
上升沿时移位寄存器的数据进入数据存储寄存器,下降沿时存储寄存器数据不变。通常将ST_CP置为低电平,当移位结束后,在ST_CP端产生一个正脉冲,更新显示数据。
.
.
.
该程序最难理解的地方就是下面这部分函数,需要把上面的74HC595的引脚功能理解透彻,再结合下面程序具体分析哈。具体的备注在上面的代码块里面方的也有,大家根据习惯看哈(我知道没多少人看,主要是给自己留作笔记看)
void Show(uint32_t shi,uint32_t ge)
{
uint32_t k,i;
for(k=0;k<8;k++)
//下面的代码要循环8次,直到把整个数据的所有二进制数位遍历一遍
{
SCLK_RESET;
//数据移位信号先为低电平,为移位准备
if((ge&0x80)==0x80)
//如果所给的ge数据的二进制形式的最高位和0x80(10000000)相与后值不变,即最高位是1
{
SDI_SET;
//将该数据的最高位1送入数据缓冲区
}
else
//如果不是的话
SDI_RESET ;
//将该数据最高位的0送入数据缓冲区
ge= ge<<1;
//让ge的二进制数据整个左移一位,为下一次判断次高位做准备
SCLK_SET ;
//让数据寄存器中的数据移位(Q0->Q1->Q2–>Q3–>…–>Q7)
}
LOAD_RESET ;
//先确认拉低
LOAD_SET;
//上升沿时移位寄存器的数据进入数据存储寄存器,ST_CP端产生一个正脉冲,更新显示数据
for(i=0;i<8;i++)
{
SCLK_RESET;
if((shi&0x80)==0x80)
{
SDI_SET;
}
else
SDI_RESET ;
shi=shi<<1;
SCLK_SET ;
}
LOAD_RESET ;
LOAD_SET;
}
.
.
.
.
.
.
.
.
.
.
.
待补充