# Jserv mini-arm-os 學習筆記 (一)_Extra_1_按鈕x輪詢x中斷 contributed by AgainTW --- # 章節 * [【1】Jserv mini-arm-os 學習筆記_開機流程x脫離IDEx你好](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/rkJtpGdAT) * [【1】Jserv mini-arm-os 學習筆記_Extra_1_按鈕x輪詢x中斷](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/H1dYPF-10) * [Jserv mini-arm-os 學習筆記 (二)](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/B1OUX65Cp) --- # 前言 我也沒想到會有補充的出現,反正就是我在試的時候犯了一個很蠢的錯誤,但我一直以為是我用輪詢的關係導致,剛好我也做了筆記當我的[黃色小鴨](https://zh.wikipedia.org/zh-tw/%E5%B0%8F%E9%BB%84%E9%B8%AD%E8%B0%83%E8%AF%95%E6%B3%95),就順便修一下當成額外的補充XD --- # 名詞解釋 * [上拉電阻](https://zh.wikipedia.org/zh-tw/%E4%B8%8A%E6%8B%89%E7%94%B5%E9%98%BB): 是當某 GPIO 未連接設備或處於高阻抗的情況下,一種用於保證輸入訊號為預期邏輯電平的電阻元件。筆記所使用的晶片和開發版本身已經內至有上拉電路和上拉電阻。 --- # 輪詢(Pooling) 讀取周邊(peripheral)的方式有很多種,像是輪詢、中斷和 DMA,它們各有優缺點。而為了理解它們以及了解如何實作,我們將使用輪詢以及中斷來實際讀取按鈕的狀態。 * **輪詢**: 由處理器定時發出詢問,依序詢問每一個週邊是否需要服務,有即給予服務,服務結束後再問下一個週邊,接著不斷週而復始。實作容易,但效率偏低,譬如說當有一個周邊需要大量資源處理時,供給給其他周邊服務的速度就會大幅下降。 * **中斷**: 是用以提高電腦工作效率、增強電腦功能的一項重要技術。指處理器接收到來自硬體或軟體的訊號,根據訊號進行處理,並且中斷可以分為硬體中斷和軟體中斷。 * **DMA**: 允許某些電腦內部的周邊可以獨立地直接讀寫記憶體,而不需中央處理器(CPU)介入處理。 ## 按鈕狀態讀取 接下來,我們將使用 stm32f429I-DISC1 讀取外部 buttom 的狀態,並透過內建 LED 顯示。. ## 腳位設定 | GPIOx | PIN | 名稱 | 功能 | |:-----:|:---:|:----:| --------------- | | G | 13 | PG13 | 內部 LED | | A | 13 | PA13 | 控制 LED 的按鈕 | ## 暫存器設定 * LED 部分的設定參考[前一篇](https://hackmd.io/@nfUUgsYRTGy81y5d9AYOyg/rkJtpGdAT),並且這次只需要配置 PG13 就好。 * 按鈕設定,我們選用 PA13 作為讀值的腳位: 1. 順便啟用(enable) A 號 GPIO port 的時鐘。 2. 配置 A 號 GPIO port 的 13 腳(PA13)的讀寫模式。 3. 配置 A 號 GPIO port 的 PA13 為上拉電阻。 4. 讀取 A 號 GPIO port PA13 的值。 * 根據手冊查找暫存器設定 * GPIO 輸入暫存器 *  ## 硬體接線 因為我找不到一樣的板子,我就找了一塊差不多的開發板湊合著演示。我是使用 Fritzing 繪製硬體接線。  ## 程式碼撰寫 * Project struct ```shell / ├── main.c ├── main.ld └── makefile ``` ### ```main.c``` 因為已經是補充了,這邊只解說要增加或修改的部分。 * 增加 GPIO_A 的位址定義 ```C= #define GPIO_A_ADDR 0x40020000 ``` * 定義 GPIO_A 的模式、上/下拉和讀值的偏移量 ```C= #define GPIO_A_PORTMODE (*((volatile unsigned long *) GPIO_A_ADDR)) #define GPIO_A_PUPD (*((volatile unsigned long *) (GPIO_A_ADDR+0xC))) #define GPIO_A_ID (*((volatile unsigned long *) (GPIO_A_ADDR+0x10))) ``` * 修改時鐘設定,因為 GPIO_A 也要吃 clock ```C= // set clock RCC_AHB1_PERI_ENBLR_ADDR |= ((0x00000001<<6) | 0x00000001); // Enalbe GPIO A, G clock ``` * 設定 GPIO_A 的 PA13 為輸出,並且為上拉電阻 ```C= // set buttom GPIO_A_PORTMODE &= ~(0x3 << 26); // Set PG13 mode to GPIO GPIO_A_PUPD |= (0x1 << 26); // Set PA13 to pull-up ``` * 主程式的部分 * 設定 PG13 內部 LED 常亮 * 透過 if 迴圈不斷地在主程式內讀取 PA13 的讀值(**輪詢**) * 透過和 ```0x1<<13``` 做 and 運算,作為讀取 GPIO_A_ID PA13 的遮罩 * 因為是上拉電阻,所以當 PA13 不為 1 時進入迴圈 * 當 PA13 狀態仍舊一致時(```while```判斷),將 PG13 設定為 0 * **增加延遲,不然 LED 滅的狀態會看起來像沒暗** ```C= while(1) { GPIO_G_PORT_BSRR = 0x00002000; if(!(GPIO_A_ID&(0x1<<13))){ while(!(GPIO_A_ID&(0x1<<13))){ GPIO_G_PORT_BSRR = 0x20000000; for(i=0;i<1000000;i++); } } } ``` ### ```main.ld``` 不需要任何修改。 ### ```makefile``` 不需要任何修改。 ## 實際影片 --- # 為何要使用外部中斷(External Interrupt) ### ```main.c``` ```C= ``` ### ```main.ld``` ```C= ``` ### ```makefile``` ```C= ``` # 備註 * 如果遇到無法燒錄的問題,可以嘗試將 3.3 V 電源接到 Boot0 上再嘗試燒錄。 --- # 參考 1. [The STM32F429I-DISCO Tutorial Series, Part 5: GPIO: Lighting an LED when the Button is Pressed Using Polling](https://thehackerworkshop.com/?p=1271) 2. [Library 02- STM32F429 Discovery GPIO tutorial with onboard leds and button](https://stm32f4-discovery.net/2014/04/stm32f429-discovery-gpio-tutorial-with-onboard-leds-and-button/) 3. [明瞭STM32-GPIO理論基礎知識篇之寄存器原理](https://www.cnblogs.com/Sharemaker/p/17281410.html) 4. [STM32 GPIO操作指导](https://blog.csdn.net/XYJ_Tiger/article/details/124771563) 5. [STM32 無法燒錄解決方式](https://hackmd.io/@ncrl-flight-control-project/Hkxt_3vrq) 6. [External Interrupt using Registers](https://controllerstech.com/external-interrupt-using-registers/) 7. [GitHub: libopencm3](https://github.com/libopencm3/libopencm3/tree/master/include/libopencm3)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up