STM32筆記(24):七段顯示器顯示數字

過去從使用 Arduino 做過七段顯示器的實做來顯示數字,有關七段顯示器的基本概念,可參考:Arduino筆記(51):7段顯示器LED的應用

七段顯示器內部構造都是由 8 個 LED 發光二極體所組成,其中七個是筆劃,另外一個是小數點,如下圖所示,依順時針方向分別為 A, B, C, D, E, F, G 以及小數點 DP  (decimal point):

撰寫控制程式前,要先確定七段顯示器是共陰極或共陽極,以我的七段顯示器為例,是共陽極的,要將 COM 這個接點接到 STM32 的 3.3v,其他就依照上圖 A~G 分別接到 STM32 的 PA1~PA7。若要顯示 0,則將圖中的 G 設為高電位,就會熄滅,呈現 0 這個數字;若要顯示 1,則將 B 及 C 兩個點設為低電位,就會亮起,呈現 1 這個數字...餘此類推。寫成程式如下,使用 case 判斷數字,點亮對應的 LED 。
case 0:
	GPIO_ResetBits(SEG_PORT, SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F);
	break;
case 1:
	GPIO_ResetBits(SEG_PORT, SEG_B|SEG_C);
	break;

另外一種更簡單的方式是一次使用 16 位元寫入 GPIOA (或其他 GPIOx),用來表示 PA0~PA15 的 Pin 腳電位,我將接腳分別從 PA1 接到 PA7,代表上圖的 A~G。若要顯示 0,則將圖中的 G 設為高電位,這時要將 16 進位的 bit 7 設為 1,再使用 GPIO_Write() 函式將 16 位元一次寫入,就會呈現 0 這個數字;若要顯示 1,則將 B 及 C 兩個點設為低電位,這時將 3 及 4 位元設定為 0 (因為從 PA1 開始安裝排線,最低位還有一個 PA0,這個位元要填 0),就會顯示 1 這個數字,請看下表紅色欄位的部分,再將這 16 位的二進位,換算成 16 進位即可,得到 0x80, 0xf2...餘此類推。

要特別注意的是一整段的 GPIOx 有 16 個引腳,要使用這個方法,要注意其他引腳是否有接其他外部設備,如果有,寫入 16 位元時,要特別注意是否會影響到其電位高低。
數字PA15PA14PA13PA12PA11PA10PA9PA8PA7PA6PA5PA4PA3PA2PA1PA016進位
000000000100000000x80
100000000111100100xf2
200000000010010000x48
300000000011000000x60
400000000001100100x32
500000000001001000x24
600000000000001000x04
700000000111100000xf0
800000000000000000x00
900000000001000000x20


[材料]

  • STM32F103C8T6 主板 x 1
  • 七段顯示器 x 1
  • STLINK V2 模擬下載器 x 1
  • 麵包板 x 1
  • 連接線 x N 條

[接線圖]

STM32 的 Pin 與七段顯示器的接腳如下:
STM32F103x七段顯示器
PA01 A
PA02 B
PA03 C
PA04 D
PA05 E
PA06 F
PA07 G
3V3COM


[程式]

主程式一開始先對七段顯示器進行初始化,進入迴圈循環後就利用 for 迴圈顯示 0~9,再另一個 for 迴圈倒數從 9 到 0,主程式 main.c 如下:
#include "stm32f10x.h"
#include "delay.h"
#include "segment.h"

int main(void) 
{

	delay_init();  
	Segment_Init();

	while (1)
	{
		for(int x=0;x<10;x++){	
			Segment_Display(x);
			delay_ms(1000);
			GPIO_SetBits(SEG_PORT, SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G);
		}
		delay_ms(3000);
				
		int y=9;
		for(int x=0;x<10;x++){
			Segment_Display2(y);
			y--;
			delay_ms(1000);
			GPIO_SetBits(SEG_PORT, SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G);
		}
		delay_ms(3000);

	}
}

Segment.c 程式如下:
#include "stm32f10x.h"
#include "segment.h"
#include "delay.h"

void Segment_Init(void){
	// 設定 GPIO    
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(SEG_PORT, &GPIO_InitStructure);
	
	GPIO_SetBits(SEG_PORT, SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G);
}

void Segment_Display(u8 num){

	switch(num)
	{
		case 0:
			GPIO_ResetBits(SEG_PORT, SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F);
			break;

		case 1:
			GPIO_ResetBits(SEG_PORT, SEG_B|SEG_C);
			break;

		case 2:
			GPIO_ResetBits(SEG_PORT, SEG_A|SEG_B|SEG_D|SEG_E|SEG_G);
			break;

		case 3:
			GPIO_ResetBits(SEG_PORT, SEG_A|SEG_B|SEG_C|SEG_D|SEG_G);
			break;

		case 4:
			GPIO_ResetBits(SEG_PORT, SEG_B|SEG_C|SEG_F|SEG_G);
			break;

		case 5:
			GPIO_ResetBits(SEG_PORT, SEG_A|SEG_C|SEG_D|SEG_F|SEG_G);
			break;

		case 6:
			GPIO_ResetBits(SEG_PORT, SEG_A|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G);
			break;

		case 7:
			GPIO_ResetBits(SEG_PORT, SEG_A|SEG_B|SEG_C);
			break;

		case 8:
			GPIO_ResetBits(SEG_PORT, SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G);
			break;

		case 9:
			GPIO_ResetBits(SEG_PORT, SEG_A|SEG_B|SEG_C|SEG_D|SEG_F|SEG_G);
			break;

		default:
			break;
	}	
}	

void Segment_Display2(u8 num){
	uint16_t SEGTAB[10]={0x80,0xf2,0x48,0x60,0x32,0x24,0x04,0xf0,0x00,0x20};
	if(num >= 10)
		return;
	GPIO_Write(SEG_PORT, SEGTAB[num]);
}



Segment.h 程式如下:
#ifndef __SEGMENT_H
#define __SEGMENT_H

#define SEG_PORT GPIOA

#define SEG_A GPIO_Pin_1
#define SEG_B GPIO_Pin_2
#define SEG_C GPIO_Pin_3
#define SEG_D GPIO_Pin_4
#define SEG_E GPIO_Pin_5
#define SEG_F GPIO_Pin_6
#define SEG_G GPIO_Pin_7

void Segment_Init(void);
void Segment_Display (u8 num);
void Segment_Display2(u8 num);

#endif

完整的程式請參考 Github:10. 7-segment Display

[結果]

使用第一種方式顯示 0~9 數字,再用第二種方式將數字從 9 顯示到 0,如下影片:

[參考資料]


Post a Comment

較新的 較舊