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;
}
.
.
.
.
.
.
.
.
.
.
.
待補充