STM32F103C8芯片流水燈
- 一、STM32F103C8T6簡介
- 二、點燈
- (一)打開時鐘
- (二)初始化
- (三) 設定低電平
- 三、keil創建專案
- 四、連接電路
- 五、編譯燒錄代碼
- (一)編譯
- (二)燒錄準備作業
- (三)燒錄程式
- (四)結果
- 六、匯編程式實作
- 七、總結
- 八、參考資料
一、STM32F103C8T6簡介
STM32F103C8T6是一款由意法半導體公司(ST)推出的基于Cortex-M3內核的32位微控制器,硬體采用LQFP48封裝,屬于ST公司微控制器中的STM32系列,所有的資料都可以在野火官網上下載野火資料下載中心
二、點燈
點亮LED燈,需要用到GPIO埠,
為了點亮LED燈,需要三個步驟:
- 打開GPIO口的時鐘
- 初始化GPIO口(選擇推挽輸出)
- 設定低電平
(一)打開時鐘
- GPIO的地址:

- 時鐘的地址:

-

即0x40021018,則打開三個IO口的時鐘需要將三個位都置1:
#define RCC_APB2ENR (*(unsigned int *)0x40021018)
// 打開時鐘
RCC_APB2ENR |= (1<<3); // 打開 GPIOB 時鐘
RCC_APB2ENR |= (1<<4); // 打開 GPIOC 時鐘
RCC_APB2ENR |= (1<<2); // 打開 GPIOA 時鐘
(二)初始化
GPIO口有八種模式:
- 輸入浮空
- 輸入上拉
- 輸入下拉
- 模擬輸入
- 開漏輸出
- 推挽式輸出
- 推挽式復用功能
- 開漏復用功能
這里使用推挽輸出
埠1-7為低,埠8-15為高,每個引腳由四個位控制,
以GPIOB和0號引腳(B0)為例,將其設定為推挽輸出,并設定最大速度為10MHz,則將控制B0的四個位設定為0001:

#define GPIOB_CRL (*(unsigned int *)0x40010c00)
// 最后四位變為0001
GPIOB_CRL |= (1<<0); // 最后一位變1
GPIOB_CRL &= ~(0xE<<0); // 倒數2、3、4位變0
對于GPIOB的B0、GPIOC的C15、GPIOA的A0,設定如下:
#define GPIOB_CRL (*(unsigned int *)0x40010C00)
#define GPIOC_CRH (*(unsigned int *)0x40011004)
#define GPIOA_CRL (*(unsigned int *)0x40010800)
// 配置 GPIO 口為推免輸出
// GPIOB----最后四位為0001
GPIOB_CRL |= (1<<0); // 最后一位變1
GPIOB_CRL &= ~(0xE<<0); // 倒數2、3、4位變0
// GPIOC----前四位為0001
GPIOC_CRH |= (1<<28); // 第四位變1
GPIOC_CRH &= ~(0xE0000000); // 前三位變0
// GPIOA----最后四位為0001
GPIOA_CRL |= (1<<0); // 最后一位變1
GPIOA_CRL &= ~(0xE<<0); // 倒數2、3、4位變0
(三) 設定低電平

輸出高電平則為1,低電平則為0
以GPIOB和0號引腳(B0)為例,將其設定為低電平
#define GPIOB_ODR (*(unsigned int *)0x40010C0C)
GPIOB_ODR &= ~(1<<0); // 最后一位變0
對于GPIOB的B0、GPIOC的C15、GPIOA的A0,設定如下:
#define GPIOB_ODR (*(unsigned int *)0x40010C0C)
#define GPIOC_ODR (*(unsigned int *)0x4001100C)
#define GPIOA_ODR (*(unsigned int *)0x4001080C)
GPIOB_ODR &= ~(1<<0); //最后一位變為0
GPIOC_ODR &= ~(1<<15); //倒數16位變為0
GPIOA_ODR &= ~(1<<0); //最后一位變為
三、keil創建專案
1.新建uVision專案

2.選擇合適位置命名保存

3.芯片選擇STM32F103下的STM32F103C8


4.把startup_stm32f10x_md.s檔案復制粘貼到剛才創建專案檔案目錄下,一般位于野火【STM32F103C8T6-核心板】資料/3-USART1接發/Libraries/CMSIS/startup/目錄下


5.引入startup_stm32f10x_md.s


6.新建main.c檔案


7.main.c代碼
#define GPIOB_BASE 0x40010C00
#define GPIOC_BASE 0x40011000
#define GPIOA_BASE 0x40010800
#define RCC_APB2ENR (*(unsigned int *)0x40021018)
#define GPIOB_CRL (*(unsigned int *)0x40010C00)
#define GPIOC_CRH (*(unsigned int *)0x40011004)
#define GPIOA_CRL (*(unsigned int *)0x40010800)
#define GPIOB_ODR (*(unsigned int *)0x40010C0C)
#define GPIOC_ODR (*(unsigned int *)0x4001100C)
#define GPIOA_ODR (*(unsigned int *)0x4001080C)
void SystemInit(void);
void Delay_ms(volatile unsigned int);
void Delay_ms( volatile unsigned int t)
{
unsigned int i;
while(t--)
for (i=0;i<800;i++);
}
int main(){
// ????
RCC_APB2ENR |= (1<<3); // ?? GPIOB ??
RCC_APB2ENR |= (1<<4); // ?? GPIOC ??
RCC_APB2ENR |= (1<<2); // ?? GPIOA ??
// ?? GPIO ?????
// ?? GPIOB ????? 0001 (B0)
GPIOB_CRL |= (1<<0); // ???????1
GPIOB_CRL &= ~(0xE); // ???????????0
// ?? GPIOC ???? 0001 (C15)
GPIOC_CRH |= (1<<28); // ??????1
GPIOC_CRH &= ~(0xE0000000); // ??????0
// ?? GPIOA ????? 0001 (A0)
GPIOA_CRL |= (1<<0); // ???????1
GPIOA_CRL &= ~(0xE); // ???????????0
// 3?LED??????(????)
GPIOB_ODR |= (1<<0); // ???????1
GPIOC_ODR |= (1<<15); // ???15????1
GPIOA_ODR |= (1<<0); // ???????1
while(1){
GPIOB_ODR &= ~(1<<0); // ??1
Delay_ms(1000000);
GPIOB_ODR |= (1<<0); // ??1
Delay_ms(1000000);
GPIOC_ODR &= ~(1<<15); // ??2
Delay_ms(1000000);
GPIOC_ODR |= (1<<15); // ??2
Delay_ms(1000000);
GPIOA_ODR &= ~(1<<0); // ??3
Delay_ms(1000000);
GPIOA_ODR |= (1<<0); // ??3
Delay_ms(1000000);
}
}
void SystemInit(){
}
四、連接電路
對于USB轉TTL模塊和stm32f103c8t6連接
GND—GND
3v3—3v3
TXD—A10
RXD—A9


五、編譯燒錄代碼
(一)編譯
1.選擇Create hex檔案


2.bulid生成.hex檔案

3.生成成功Object/test4.hex(由于重新建過專案,test5改成了test4)

(二)燒錄準備作業
1,下載CH341SerSetup.exe,并用管理員權限安裝,加載USB串口驅動

2.下載FlyMcu.exe或者mcuisp.exe中其中一個方便燒錄


(三)燒錄程式
用FlyMcu進行燒錄



(四)結果

六、匯編程式實作
RCC_APB2ENR EQU 0x40021018;配置RCC暫存器,時鐘,0x40021018為時鐘地址
GPIOB_BASE EQU 0x40010C00
GPIOC_BASE EQU 0x40011000
GPIOA_BASE EQU 0x40010800
GPIOB_CRL EQU 0x40010C00
GPIOC_CRH EQU 0x40011004
GPIOA_CRL EQU 0x40010800
GPIOB_ODR EQU 0x40010C0C
GPIOC_ODR EQU 0x4001100C
GPIOA_ODR EQU 0x4001080C
Stack_Size EQU 0x00000400;堆疊的大小
AREA STACK, NOINIT, READWRITE, ALIGN=3 ;NOINIT: = NO Init,不初始化,READWRITE : 可讀,可寫,ALIGN =3 : 2^3 對齊,即8位元組對齊,
Stack_Mem SPACE Stack_Size
__initial_sp
AREA RESET, DATA, READONLY
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
AREA |.text|, CODE, READONLY
THUMB
REQUIRE8
PRESERVE8
ENTRY
Reset_Handler
bl LED_Init;bl:帶鏈接的跳轉指令,當使用該指令跳轉時,當前地址(PC)會自動送入LR暫存器
MainLoop BL LED_ON_C
BL Delay
BL LED_OFF_C
BL Delay
BL LED_ON_A
BL Delay
BL LED_OFF_A
BL Delay
BL LED_ON_B
BL Delay
BL LED_OFF_B
BL Delay
B MainLoop;B:無條件跳轉,
LED_Init;LED初始化
PUSH {R0,R1, LR};R0,R1,LR中的值放入堆疊
;控制時鐘
LDR R0,=RCC_APB2ENR;LDR是把地址裝載到暫存器中(比如R0),
ORR R0,R0,#0x1c
LDR R1,=RCC_APB2ENR
STR R0,[R1]
;初始化GPIOA_CRL
LDR R0,=GPIOA_CRL
BIC R0,R0,#0x0fffffff;BIC 先把立即數取反,再按位與
LDR R1,=GPIOA_CRL
STR R0,[R1]
LDR R0,=GPIOA_CRL
ORR R0,#0x00000001
LDR R1,=GPIOA_CRL
STR R0,[R1]
;將PA0置1
MOV R0,#0x01
LDR R1,=GPIOA_ORD
STR R0,[R1]
;初始化GPIOB_CRL
LDR R0,=GPIOB_CRL
BIC R0,R0,#0x0fffffff;BIC 先把立即數取反,再按位與
LDR R1,=GPIOB_CRL
STR R0,[R1]
LDR R0,=GPIOB_CRL
ORR R0,#0x00000001
LDR R1,=GPIOB_CRL
STR R0,[R1]
;將PB0置1
MOV R0,#0x01
LDR R1,=GPIOA_ORD
STR R0,[R1]
;初始化GPIOC
LDR R0,=GPIOC_CRH
BIC R0,R0,#0x0fffffff
LDR R1,=GPIOC_CRH
STR R0,[R1]
LDR R0,=GPIOC_CRH
ORR R0,#0x01000000
LDR R1,=GPIOC_CRH
STR R0,[R1]
;將PC15置1
MOV R0,#0x8000
LDR R1,=GPIOC_ORD
STR R0,[R1]
POP {R0,R1,PC};將堆疊中之前存的R0,R1,LR的值返還給R0,R1,PC
LED_ON_A
PUSH {R0,R1, LR}
MOV R0,#0x00
LDR R1,=GPIOA_ORD
STR R0,[R1]
POP {R0,R1,PC}
LED_OFF_A
PUSH {R0,R1, LR}
MOV R0,#0x01
LDR R1,=GPIOA_ORD
STR R0,[R1]
POP {R0,R1,PC}
LED_ON_B;亮燈
PUSH {R0,R1, LR}
MOV R0,#0x00
LDR R1,=GPIOB_ORD
STR R0,[R1]
POP {R0,R1,PC}
LED_OFF_B;熄燈
PUSH {R0,R1, LR}
MOV R0,#0x01
LDR R1,=GPIOB_ORD
STR R0,[R1]
POP {R0,R1,PC}
LED_ON_C;亮燈
PUSH {R0,R1, LR}
MOV R0,#0x00
LDR R1,=GPIOC_ORD
STR R0,[R1]
POP {R0,R1,PC}
LED_OFF_C;熄燈
PUSH {R0,R1, LR}
MOV R0,#0x0100
LDR R1,=GPIOC_ORD
STR R0,[R1]
POP {R0,R1,PC}
Delay
PUSH {R0,R1, LR}
MOVS R0,#0
MOVS R1,#0
MOVS R2,#0
DelayLoop0
ADDS R0,R0,#1
CMP R0,#330
BCC DelayLoop0
MOVS R0,#0
ADDS R1,R1,#1
CMP R1,#330
BCC DelayLoop0
MOVS R0,#0
MOVS R1,#0
ADDS R2,R2,#1
CMP R2,#15
BCC DelayLoop0
POP {R0,R1,PC}
NOP
END
七、總結
stm32芯片的流水燈實驗對動手能力等各個方面都很考量,代碼燒錄失敗,打不開串口,可能是沒有下載驅動USB驅動失敗,或者是線路問題,這次實驗對stm32芯片各個串口輸入輸出,作業原理、暫存器地址等有了一定了解,個人掌握的程度不夠深,會出現各個環節無法聯系的問題,學無止境,通過不斷的學習會更加了解這些內容和找到合適的方法,
八、參考資料
STM32F103C8芯片流水燈
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/325814.html
標籤:其他

