2019年8月28日 星期三

Hello World--STM32F205RBT6在MDK5的應用範例

上一篇文章提到

在 CubeMX 可以產生多種編譯環境中常見的程式碼

其中包含 IAR 的 EWARM V7/V8

Keil 的 MDK-ARM V4/V5

還有自家最新推出的 CubeIDE

與第三方(AC6)合作的 SW4STM32

這些編譯環境都可以被 CubeMX 所支援

不過我本身對 MDK 的環境比較熟悉

所以才會以 MDK5 作為範例

如果有機會

建議可以嘗試一下 CubeIDE 或 SW4STM32

官方資源與開源環境是新時代的趨勢

自由度越高的環境才能被更多的使用者接受

等我熟悉過 CubeIDE 及 SW4STM32 後再來跟大家分享

暫時先看看 MDK5 的範例吧 (以官方試用版的空間限制就能完成的專案)

==========================================================

由 CubeMX 所產生的 MDK5 程式碼會包含以下幾個資料夾:

1. Drivers:其中包括 CMSIS (Cortex MCU Software Interface Standard)
及 STM32F2xx_HAL_Driver (STM 官方 HAL 庫)

2. Inc:

程式所需的 include 檔

3. MDK-ARM:

包含專案捷徑及除錯所需的連結檔、燒錄檔

4. Src:

主要程式的原始碼 (使用者修改專用)


然後還有一個 Hello.ioc 的 CubeMX 專用 IO 編輯檔

剛剛產生的檔案中

MDK-ARM資料夾內的資料應該都是空的

因為專案本身還沒經過編譯

所以連結檔與燒錄檔都尚未產生

等第一次編譯過後就會有對應的檔案出現

今天的目標是要完成 Hello World 的任務

所以先進入MDK-ARM的資料夾中

由 Hello.uvprojx 的專案檔開啟專案

這是站長習慣的開啟方式

你也可以先打開 MDK5 由 Project -> Open Project 的方式來開啟

因為是第一次開啟專案

所以 Project 應該還沒把專案列入最近清單中

等編譯完成後就可以由最近清單中去開啟專案

另外

進入專案後第一件要確認的就是燒錄環境的設定

如果您使用的是 ST LINK 當作燒錄的工具

那麼就可以忽略接下來的步驟

不過建議還是檢查一下比較保險

我所使用的是 MDK5 專用的 ULINK2

與專案所建立的 ST LINK 是不一樣的工具

所以要先到 Flash -> Configure Falsh Tools... 中

將 Debug 欄位裡的工具更改為 ULINK2

您可以依照自己所使用的工具進行修改

別忘了要替燒錄工具的韌體進行更新

免得不支援選用的 MCU 就 GG 了

==========================================================

要完成 Hello World 的任務

有幾個重要的觀念要先建立

一般來說

周邊功能有三種方式可以呼叫

第一種是用輪詢

第二種是用中斷

第三種是DMA

這個範例會先以輪詢的方式進行撰寫

先驗證IO動作是正確的

之後再嘗試中斷與DMA的寫法

其次

標準 C 語言有內建通訊的函式 printf ()

要使用這個功能必須引用 <stdio.h> 這個開頭檔

否則編譯過程中會發生語法錯誤

由於通訊功能相關的程式碼放在 usart.c 當中

所以首先要改寫的程式便從 usart.c 開始

==========================================================

/* USER CODE BEGIN 0 */

#include <stdio.h>

/* USER CODE END 0 */

/* USER CODE BEGIN 1 */

#ifdef __GNUC__
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
  HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF);
  return ch;
}

/* USER CODE END 1 */

在 usart.c 中找到 /* USER CODE BEGIN 0 */ 與 /* USER CODE BEGIN 1 */ 的位置

加入上方的程式碼

因為我們接下來會引用 printf 函式

編譯時會檢查編譯環境的設定

所以定義了編譯環境所必須的參數

而 HAL_UART_Transmit 函式則是 HAL 庫內建功能

在 stm32f2xx_hal_uart.c 中可以找到

功能是將 printf 所要丟出的字串一個一個 Byte 傳送出去

==========================================================

/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */

/* USER CODE BEGIN 3 */
printf("\r\n Hello World !! \r\n");
HAL_Delay(1000);
  }
/* USER CODE END 3 */

接下來到主程式 main.c 中

找到 /* USER CODE BEGIN Includes */ 及 /* USER CODE BEGIN 3 */

把上面的程式碼加入

其中 HAL_Dealy 約是每個計數 1mS 的延遲 (在 stm32f2xx_hal.c 中)

設定1000為1秒鐘延遲的意思

然後點擊 Rebuild 鍵先進行第一次編譯動作

之後就等待 MDK5 編譯完成

第一次編譯通常會花上一些時間

完成後執行 Load 將程式燒錄到 MCU 中

如果前面的燒錄工具有設定正確的話

應該很快就可以燒錄(下載)成功

接上 USB<->UART 工具或任何可以觀看 UART 通訊資料的工具

你就可以看到 Hello World !! 字樣

==========================================================

如果你不是很習慣作業系統的寫法

不想使用 printf 來傳送資料

那可以怎麼修改呢?

/* USER CODE BEGIN PV */
uint8_t Enter[] = { 0x0d, 0x0a };
uint8_t Hello[] = { "Hello World !!!" };
/* USER CODE END PV */

/* USER CODE BEGIN 3 */
HAL_UART_Transmit (&huart3, Enter, sizeof(Enter), 0xffff);
HAL_UART_Transmit (&huart3, Hello, sizeof(Hello)-1, 0xffff);
HAL_UART_Transmit (&huart3, Enter, sizeof(Enter), 0xffff);
HAL_Delay(1000);
  }
/* USER CODE END 3 */

回歸到單晶片的概念

就是找到傳送的函式

把要丟出去的字串定義好丟出去就可以了

所以可以不要修改 usart.c 中的內容

只在 main.c 中找到 /* USER CODE BEGIN PV */ 及 /* USER CODE BEGIN 3 */

將上面的程式碼寫入對應的位置上

一樣可以看到 Hello World !!! 的字樣

其中

由於宣告為字串的矩陣會多帶一個空字串

所以使用sizeof()這個功能時要將空字串的計數減掉 [sizeof(Hello)-1]

不然會在通訊中多看到一個 0x00 的碼躲在 Hello World !!!後面

==========================================================

最後要提一下 CubeMX 所要帶給我們的改變與新思維:

第一

不要再以硬體底層的概念來看單晶片程式

因為現在的單晶片都不再是以往簡單幾個周邊功能而已

各個周邊之間的關聯性與複雜度都今非昔比

建立以系統觀的思維來看待程式

嘗試以作業系統的寫法來修正以往的撰寫習慣

可以提高程式的可攜性與移植性

避開重複開發以縮短專案完成的時間

第二

我們不是單晶片大廠的員工

也不是設計單晶片的設計師

不應該為單晶片的驅動與除錯負責

這應該是單晶片大廠所要克服的功課

在高度分工的科技時代

如果還要工程師從頭到尾把晶片廠的問題一一克服才開始開發專案

那開發的進度鐵定落後到天荒地老

並不是我們不具備解決問題的能力

也不是我們缺乏學習的動力與毅力

而是在商言商--時間就是金錢

很多舊時代的大廠還停留在工程師就是要解決所有的開發問題

而忽略分工的責任劃分與時間、專案管理的問題

甚至把問題都怪罪到研發工程師的身上

認為他們程度差且懶惰又不負責任

這是非常落伍且不公平的

第三

工欲善其事,必先利其器

如果有更好的工具可以用

就不要因為習慣了舊工具就排斥接觸新工具

每個學習都有陣痛期

但如果陣痛可以帶來脫胎換骨的大提升

那為何不痛一下就好?

而要一直忍受效率不好的開發工具

讓自己的競爭力越來越不好呢?

人本來就是活到老學到老

不是嗎?

希望你會喜歡這篇文章的介紹

下一篇我們要探討一下中斷與DMA的用法

敬請繼續期待

沒有留言:

張貼留言