過去從使用 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 。
另外一種更簡單的方式是一次使用 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 位元時,要特別注意是否會影響到其電位高低。
Segment.c 程式如下:
Segment.h 程式如下:
七段顯示器內部構造都是由 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 位元時,要特別注意是否會影響到其電位高低。
數字 | PA15 | PA14 | PA13 | PA12 | PA11 | PA10 | PA9 | PA8 | PA7 | PA6 | PA5 | PA4 | PA3 | PA2 | PA1 | PA0 | 16進位 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0x80 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0xf2 |
2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0x48 |
3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0x60 |
4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0x32 |
5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0x24 |
6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0x04 |
7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0xf0 |
8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0x00 |
9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0x20 |
[材料]
- 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 |
3V3 | COM |
[程式]
主程式一開始先對七段顯示器進行初始化,進入迴圈循環後就利用 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
張貼留言