Keil MDK + STM32F4

<rawat.s>
9 min readFeb 20, 2021

ในบทความนี้ นำเสนอขั้นตอนการใช้งานซอฟต์แวร์ ARM / Keil MDK (Microcontroller Development Kit) ในเบื้องต้น เพื่อนำมาใช้งานกับบอร์ดไมโครคอนโทรลเลอร์ ตระกูล STM32F4 (ARM Cortex-M4F) ต่อไปนี้

  • BlackPill Board: STM32F411CEU6, Flash 512 KB SRAM 128KB
  • STM32F4 Discovery Board: STM32F407VGT6, 1024KB Flash, 192kB SRAM

MDK เวอร์ชันที่นำมาทดลองใช้คือ v5.33 ซึ่งประกอบด้วยซอฟต์แวร์ต่าง ๆ เช่น

  • ARM C/C++Compiler
  • uVision IDE (Simulator / Debugger)
  • Software Packs

เพิ่มเติม: แนะนำให้ติดตั้งซอฟต์แวร์ STM32 ST-LINK Utility เพื่อใช้งานสำหรับ ST-Link/V2 Debugger

ขั้นตอนที่ 1: ดาวน์โหลดและติดตั้งซอฟต์แวร์ Keil MDK

ให้ดาวน์โหลดไฟล์สำหรับติดตั้งใช้งาน (สำหรับ Windows เท่านั้น) ได้จาก https://www2.keil.com/mdk5 แล้วเลือกใช้งานแบบ MDK-Lite ผู้ใช้จะสามารถใช้งานได้ฟรี แต่มีข้อจำกัดที่ขนาดของโปรแกรมที่ได้จากการคอมไพล์โค้ดแล้ว (Program Size) จะต้องไม่เกิน 32 KB

ขั้นตอนที่ 2: เปิดใช้งาน Keil uVision MDK และติดตั้ง Software Packs

ไมโครคอนโทรลเลอร์ที่เราจะลองใช้งานคือ STM32F4 ดังนั้น จะต้องติดตั้ง Software Packs ของ Keil MDK (ดาวน์โหลดจากอินเทอร์เน็ต)

ในหน้าต่าง Pack Installer ให้เลือก Device เช่น STM32F411 หรือ STM32F407 ในช่องทางซ้าย จากนั้นในช่องทางขวา ให้ดูตรง Device Specific แล้วเลือก Keil:STM32F4xx_DFP เลือกเวอร์ชันลา่สุด แล้วกดปุ่ม Install และเมื่อได้ติดตั้งแล้ว จะเปลี่ยนสถานะเป็น “Up to date”

เพิ่มเติม: ในกรณีที่เราเลือกใช้ไมโครคอนโทรลเลอร์ตระกูลอื่น เช่น MSP432 ของบริษัท Texas Instruments หรือ ATSAMD21 หรือ ATSAM3X8E ของบริษัท Atmel / Microchip ก็ให้เลือกติดตั้ง Software Packs ที่เกี่ยวข้อง

ขั้นตอนที่ 3: สร้างโปรเจกต์ใหม่

เลือกทำเมนู Project > New uVision Project … เพื่อเริ่มต้นสร้างโปรเจกต์ใหม่ จากนั้นให้สร้าง Folder ใหม่สำหรับเก็บไฟล์ต่าง ๆ ของโปรเจกต์ พร้อมตั้งชื่อไฟล์

ในตัวอย่างนี้ เราจะมาลองสร้างโปรเจกต์สำหรับ STM32F411CEU6 เพื่อสาธิตการเขียนโค้ดและทำให้ LED ที่อยู่บนบอร์ด BlackPill กระพริบได้

เมื่อสร้างโปรเจกต์แล้ว ถัดไปจะต้องเลือก Device จาก Software Packs ในกรณีนี้ จะต้องเลือก STM32F411CEUx

จากนั้นไปยังหน้าต่าง “Manage Run-Time Environment” ซึ่งจะต้องเลือกว่า ต้องการใช้ไลบรารีหรือ API ใดบ้าง

โดยทั่วไปแล้ว ในเบื้องต้น ให้เลือกตามตัวอย่างในรูป เช่น

  • CMSIS CORE
  • Device: Startup File
  • STM32Cube Framework (API): Classic
  • STM32Cube HAL: Common, Cortex, PWR, RCC, GPIO

เมื่อได้ตั้งค่าใช้งานแล้ว ก็กดปุ่ม OK จากนั้นจะกลับสู่หน้าต่างหลักของ uVision IDE พร้อมไฟล์ต่าง ๆ ที่ถูกใส่เพิ่มเข้ามาโดยอัตโนมัติ

ข้อสังเกต: ถ้าต้องการใช้งาน Peripherals ของ STM32F4 นอกเหนือจาก GPIO ก็สามารถคลิกเพิ่มได้ เช่น UART

ขั้นตอนที่ 4: เพิ่มไฟล์ main.c และเขียนโค้ดตามตัวอย่าง

ถัดไปเป็นการสร้างไฟล์ main.c และเพิ่มลงในโปรเจกต์ โดยไปที่ Target 1 > Source Group 1 > Add New Item to Group “Source Group 1” แล้วเลือกชนิดของไฟล์เป็น C File (.c) และตั้งชื่อไฟล์ main.c

โค้ดตัวอย่างต่อไปนี้ เมื่อนำไปใช้กับบอร์ด BlackPill STM32F411CEU6 จะทำให้ LED ที่อยู่บนบอร์ด ซึ่งตรงกับขา PC13 กระพริบได้

ในตัวอย่างนี้ มีการสร้างฟังก์ชัน void LED_Config(void) { … } เพื่อกำหนดค่าที่เกี่ยวข้องกับ GPIO Port C โดยให้ขา GPIOC หมายเลข 13 ของพอร์ตดังกล่าว เป็นเอาต์พุต และให้มีสถานะเริ่มต้นเป็น High โดยใช้ฟังก์ชันของ STM32 HAL ได้แก่ HAL_GPIO_Init() และ HAL_GPIO_WritePin()

นอกจากนั้นยังต้องมีการเปิดสัญญาณ Clock ที่ใช้สำหรับวงจร GPIO Port C ด้วย โดยใช้คำสั่ง __GPIOC_CLK_ENABLE()

การใช้คำสั่งเกี่ยวกับเวลาของระบบ จะใช้วงจรภายในที่มีชื่อว่า System Tick Timer และตั้งค่าให้เกิดอินเทอร์รัพท์ไว้ทุก ๆ 1 มิลลิวินาที ดังนั้นจึงต้องสร้างฟังก์ชัน void SysTick_Handler(void) { … } ตามตัวอย่าง เพื่อทำหน้าที่เป็น ISR (Interrupt Service Routine) สำหรับ SysTick Timer

ฟังก์ชันสำหรับ ISR ตามชื่อนี้ ได้มีการระบุชื่อเอาไว้ในไฟล์ Startup (.s) และสามารถดูได้ในไฟล์ startup_stm32f411xe.s

ดังที่กล่าวไป เมื่อเกิดอินเทอร์รัพท์จากวงจร SysTick Timer ได้ถูกตั้งค่าไว้ให้เกิดขึ้น ทุก ๆ 1 มิลลิวินาที (Default) จะต้องมีการเรียกฟังก์ชัน HAL_IncTick() เพื่อเพิ่มตัวนับหรือตัวแปร SysTick Counter ครั้งละหนึ่ง ซึ่งจำเป็นสำหรับการทำงานฟังก์ชัน HAL_Delay()

ข้อสังเกต: คำสั่งต่าง ๆ ของ STM32Cube HAL โดยทั่วไปแล้ว ก็จะมีชื่อของฟังก์ชันที่ขึ้นต้นด้วย HAL_

#include "stm32f4xx.h"  
#include "stm32f4xx_hal.h"
#define LED_PIN GPIO_PIN_13void LED_Config(void); // forward declarationvoid SysTick_Handler(void) { // ISR for SystemTick interrupt
HAL_IncTick(); // increment the system tick counter
}
int main() {
HAL_Init(); // This function must be called first
LED_Config(); // configure the GPIO port for LED output pin
while(1) {
HAL_GPIO_TogglePin( GPIOC, LED_PIN ); // toggle LED pin
HAL_Delay( 100 ); // delay for 100 msec
}
}
void LED_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure;
__GPIOC_CLK_ENABLE();
GPIO_InitStructure.Pin = LED_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init( GPIOC, &GPIO_InitStructure );
HAL_GPIO_WritePin( GPIOC, LED_PIN, GPIO_PIN_SET );
}

จากนั้นลองทำขั้นตอน Project > Build Target เพื่อลองคอมไพล์โค้ดในโปรเจกต์ เพื่อดูว่า มีข้อผิดพลาดใด ๆ หรือไม่

ขั้นตอนที่ 5: การตั้งค่าการใช้งานสำหรับ Target

ถ้าเราต้องการจะตั้งค่าการใช้งาน ให้ใช้เมาส์คลิกขวาเลือก Target 1 จากนั้นเลือก “Options for Target: Target 1”

จากนั้นจะปรากฏหน้าต่างใหม่ขึ้นมาดังรูป และจะเห็นว่า มีการแบ่งออกเป็น Tabs ต่าง ๆ เช่น ถ้าเลือก Tab “Output” ก็จะเป็นตัวเลือกสำหรับไฟล์เอาต์พุตที่ได้จากขั้นตอน Build Target

ถ้าต้องการได้ไฟล์ .hex ให้เลือก “Create HEX File” ซึ่งเป็นรูปแบบของไฟล์ที่เรานำไปใช้โปรแกรมลงชิปไมโครคอนโทรลเลอร์ได้

หรือถ้าต้องการตั้งค่าการใช้งานเกี่ยวกับคอมไพล์เลอร์ Arm Compiler 6 ก็ให้เลือก Tab “C/C++ (AC6)” เช่น การกำหนดระดับในการทำ Code Optimization โดยคอมไพล์เลอร์ เช่น -O0 (no optimization), -O1, -O2, -O3 เป็นต้น

ถ้าต้องการใช้งาน Debugger ก็ไปที่ Tab “Debug” เช่น เลือกได้ว่า จะใช้ Simulator หรือจะใช้ Hardware Debugger (ในตัวอย่างนี้ เลือกใช้อุปกรณ์ ST-Link Debugger)

ขั้นตอนที่ 6: การอัปโหลดไฟล์ .hex ไปยังบอร์ด

เมื่อได้ทำขั้นตอน Build Target สำหรับ Target 1 แล้ว จะได้ไฟล์ .hex ถัดไปจะนำ ST-Link/V2 Programmer /Debugger มาต่อกับบอร์ด BlackPill STM32F411CEU6 และเชื่อมต่อกับพอร์ต USB ของคอมพิวเตอร์ผู้ใช้

ให้ตั้งค่าการใช้งานก่อน โดยไปที่ Flash > Configure Flash Tools ซึ่งจะไปกำหนดค่าใน Tab “Utilities” และตรงช่อง “Use Target Driver for Flash Programming” ให้เลือก “ST-Link Debugger” และกดปุ่ม Settings

ในส่วนของการตั้งค่าใช้งานสำหรับ ST-Link Debugger ใน Tab “Debug” ให้ปรับลดความเร็ว Clock เช่น เลือก 2.4 MHz (ถ้าเลือกความถี่สูงไป อาจเชื่อมต่อกับอุปกรณ์ไม่ได้) และเลือกเป็น SW (หมายถึง SWD) ไม่ใช่ JTAG จากนั้นกดปุ่ม OK

ข้อสังเกต: ถ้ามีอุปกรณ์ ST-Link Debugger เชื่อมต่ออยู่ จะมีข้อมูลเกี่ยวกับ Serial Number และ Firmware Version (FW) ของอุปกรณ์ และถ้าใช้งาน อาจมีการทำขั้นตอนอัปเดตเฟิร์มแวร์ของอุปกรณ์ด้วยเมื่อเริ่มใช้งานครั้งแรก

การเชื่อมต่อระหว่างบอร์ดไมโครคอนโทรลเลอร์และอุปกรณ์ ST-Link Debugger จะใช้สายไฟ 4 เส้น เชื่อมต่อแบบ SWD Interface (Serieal Wire Debug)

  • VCC (+3.3V) — เป็นไฟเลี้ยง +3.3V (ห้ามใช้ +5V)
  • SWDIO (Data)
  • SWCLK (Clock)
  • GND
รูป: บอร์ด BlackPill STM32F411CEU6 + อุปกรณ์ ST-Link/V2
รูป: อุปกรณ์ ST-Link/V2

ถัดไปทำทำขั้นตอน Flash > Download ไฟล์ .hex จะถูกนำไปใส่ลงในหน่วยความจำ Flash ของไมโครคอนโทรเลอร์ เมื่อเสร็จแล้ว ให้กดปุ่ม RESET บนบอร์ด จากนั้นจะเห็นว่า LED บนบอร์ดจะกระพริบต่อเนื่อง

เมื่อทำถึงขั้นตอนนี้แสดงว่า เราสามารถใช้งานซอฟต์แวร์และทดลองใช้โค้ดตัวอย่างได้สำเร็จแล้ว

ขั้นตอนที่ 7: การดีบักโค้ดโดยใช้บอร์ดไมโครคอนโทรลเลอร์

การเขียนโค้ดเพื่อนำไปใช้งานกับไมโครคอนโทรลเลอร์แล้ว ถ้าต้องการตรวจสอบการทำงาน ก็สามารถเลือกใช้ได้สองวิธีคือ การใช้ Simulator หรือซอฟต์แวร์จำลองการทำงานซึ่ง uVision IDE ก็มี Simulator ไว้ให้ใช้งาน

อีกวิธีหนึ่งคือ การรันโค้ดในไมโครคอนโทรลเลอร์ แต่สามารถควบคุมการทำงานและอ่านสถานะของฮาร์ดแวร์ มาแสดงผลเชื่อมโยงกับโค้ดที่เขียนได้ เราเรียกว่า In-Circuit Debugging

เริ่มต้นขั้นตอนโดยไปที่ Debug > Start/Stop Debugging Session

เมื่อเข้าสู่ Debug Session แล้ว จะเห็นได้ว่า มี Tab “Registers” ซึ่งแสดงค่าในขณะนั้นของรีจิสเตอร์ต่าง ๆ ในซีพียู

นอกจากนั้นยังมีหน้าต่าง Disassembly ซึ่งเป็นโค้ดในภาษา Assembly ที่ได้จากการแปลงโค้ดภาษา C

การทำงานของโปรแกรมจะมาหยุดอยู่ที่คำสั่งแรก ภายในฟังก์ชัน main() ซึ่ง ในกรณีนี้ก็คือ HAL_Init() และเราสามารถกดปุ่ม Run (F5) / Start Code Execution ให้ทำงานต่อไปได้

แต่ก่อนจะให้โค้ดทำงานต่อไป ลองมาเพิ่มตำแหน่งการหยุดในโค้ดหรือที่เรียกว่า Breakpoint โดยการคลิกเลือกบรรทัดที่มีคำสั่งที่เราต้องการจะให้หยุดก่อนทำคำสั่งนั้น เมื่อคลิดเลือกแล้วจะมีวงกลมสีแสดงปรากฏขึ้น ถ้ากดอีกครั้งก็จะหายไปได้

รูป: เริ่มต้น Debug Session และหยุดการทำงานชั่วคราวก่อนทำคำสั่งแรกใน main()

เมื่อได้คลิกเลือก Breakpoint แล้ว ตามรูปตัวอย่าง ให้ลองรันโค้ดต่อไป แล้วจะมาหยุดในตำแหน่งของ Breakpoint ถัดไป ตามที่ได้กำหนดไว้ ถ้าทำไปหลาย ๆ ครั้ง จะเห็นว่า สถานะของ LED จะเปลี่ยนไป ติดหรือดับ สลับกันไป

รูป: ทำคำสั่งถัดไปและมาหยุดที่คำสั่งการเรียกฟังก์ชัน HAL_GPIO_TogglePin()
รูป: การดูสถานะการทำงานที่เกี่ยวข้องกับ Peripherals ต่าง ๆ ใน System Viewer

ดูค่าของรีจิสเตอร์ต่าง ๆ ที่เกี่ยวข้องกับ GPIO Port C ได้ใน System Viewer > GPIOC

ถ้าต้องการดูค่าในรีจิสเตอร์ต่าง ๆ ของ System Tick Timer ให้ดูได้จาก System Viewer > Core Peripherals > System Tick Timer (SysTick)

รูป: System View — System Tick Timer (SysTick)

ถัดไปมาลองโค้ดตัวอย่างที่แตกต่างออกไป เช่น ถ้าจะไม่ใช้คำสั่ง HAL_GPIO_TogglePin() เราก็สามารถเขียนโค้ดในเฉพาะฟังก์ชัน main() ได้ดังนี้

int main() {
HAL_Init();
LED_Config();
while(1) {
HAL_GPIO_WritePin( GPIOC, LED_PIN, GPIO_PIN_SET ); // PC13 high
HAL_Delay( 100 );
HAL_GPIO_WritePin( GPIOC, LED_PIN, GPIO_PIN_RESET ); // PC13 low
HAL_Delay( 100 );
}
}

หรือจะเปลี่ยนเป็นการเข้าถึงรีจิสเตอร์ ODR (Output Data Register) ของ GPIOC โดยตรงผ่านพอยน์เตอร์ ดังนี้

int main() {
HAL_Init();
LED_Config();
while(1) {
GPIOC->ODR |= (1U << 13); // PC13 high
HAL_Delay( 100 );
GPIOC->ODR &= ~(1U << 13); // PC13 low
HAL_Delay( 100 );
}
}

หรือจะเปลี่ยนไปใช้รีจิสเตอร์ BSRR (Bit Reset Set Register) ของ GPIOC เพื่อเซ็ตบิตหรือเคลียร์บิตในตำแหน่งที่ต้องการ

int main() {
HAL_Init();
LED_Config();
while(1) {
GPIOC->BSRR = (1U << 13); // set bit PC13
HAL_Delay( 100 );
GPIOC->BSRR = (1U << (13+16)); // clear bit PC13
HAL_Delay( 100 );
}
}

ขั้นตอนที่ 8: การดีบักโค้ดโดยใช้ Simulator

ถ้าไม่มีอุปกรณ์หรือบอร์ดไมโครคอนโทรลเลอร์ เราก็สามารถจำลองการทำงานของโค้ดได้ โดยจะต้องเปลี่ยนการตั้งค่าสำหรับ Debug Options ก่อน

ใน Tab “Target” ให้ลองตั้งค่า Xtal (MHz) เป็น 16.0 (ตรงกับความถี่ของ HSI: Internal High-Speed Oscillator ของ STM32F4)

เปลี่ยนจากตัวเลือก Use ST-Link Debugger ให้เป็น Use Simulator ตามรูปตัวอย่าง

ถัดไปให้สร้างไฟล์ เช่น ใช้ชื่อว่า debug.ini เพื่อใช้เป็น Initialization File สำหรับ Simulator จากนั้นให้กดปุ่ม Edit เพื่อข้อความลงในไฟล์ แล้วบันทึกการแก้ไข

MAP 0x40000000, 0x400FFFFF READ WRITE

การใช้คำสั่ง MAP เป็นการอนุญาตให้ Simulator สามารถเขียนหรืออ่านข้อมูลลงในบริเวณหน่วยความจำ ในช่วงแอดเดรส 0x4000_0000 ถึง 0x400F_FFFF ซึ่งเกี่ยวข้องกับรีจิสเตอร์ต่าง ๆ ของวงจร Peripherals ภายใน STM32F4

เมื่อเริ่มต้น Debug Session อีกครั้ง โดยใช้ Simulator และต้องการดูการเปลี่ยนแปลงค่าหรือบิตต่าง ๆในรีจิสเตอร์ เช่น ตำแหน่งบิตที่เกี่ยวข้องกับสถานะลอจิกของ LED หรือขา PC13 เช่น

  • รีจิสเตอร์ GPIOC->ODR (Address = 0x40020814) : บิตที่ 13
  • รีจิสเตอร์ GPIOS->BSRR (Address = 0x40020818) : บิตที่ 13 และบิตที่ 29 (13+16)

ก็สามารถเพิ่มนิพจน์ (Expression) ตามตัวอย่างนี้ ลงใน Watch Window (Watch 1)

และจากรายการใน Watch 1 Window เราก็สามารถนำไปใช้กับ Logic Analyzer เพื่อดูการเปลี่ยนแปลงค่าในเชิงเวลาได้ ดังนี้

จากนั้น ก็กดปุ่ม Setup… เพื่อกำหนดรูปแบบการแสดงค่าของสัญญาณใน Logic Analyzer

ให้ลองใช้โค้ดนี้สำหรับฟังก์ชัน main() แล้วทำขั้นตอน Build จากนั้นเริ่มต้น Debug Session

int main() {
HAL_Init();
LED_Config();
while(1) {
HAL_GPIO_WritePin( GPIOC, LED_PIN, GPIO_PIN_SET ); // PC13 high
HAL_Delay( 100 );
HAL_GPIO_WritePin( GPIOC, LED_PIN, GPIO_PIN_RESET ); // PC13 low
HAL_Delay( 100 );
}
}

ถ้าลองรันโค้ดใน Debug Session จะเห็นการเปลี่ยนแปลงค่าของรีจิสเตอร์ที่เกี่ยวข้อง ซึ่งก็คือ BSRR ของพอร์ต GPIOC และรูปคลื่นสัญญาณใน Logic Analyzer ตามตัวอย่าง

รูป: คลื่นสัญญาณดิจิทัลในหน้าต่าง Logic Analyzer

แต่ถ้าลองเปลี่ยนไปใช้โค้ดต่อไปนี้

int main() {
HAL_Init();
LED_Config();
while(1) {
GPIOC->ODR |= (1U << 13); // PC13 high
HAL_Delay( 100 );
GPIOC->ODR &= ~(1U << 13); // PC13 low
HAL_Delay( 100 );
}
}

จะเห็นการเปลี่ยนแปลงของรีจิสเตอร์ ODR ของพอร์ต GPOIC

ถ้าลองวัดระยะห่างระหว่างขอบขาขึ้นและขาลงของสัญญาณเอาต์พุตโดยใช้ Cursors จะเห็นว่า ได้ประมาณ 100 มิลลิวินาที (0.1 วินาที)

ขั้นตอนที่ 9: การตั้งค่าความถี่ของระบบและทดลองใช้กับฮาร์ดแวร์จริง

ในโค้ดตัวอย่างนี้ ได้มีการสร้างและใช้ฟังก์ชัน SystemClock_Config() เพื่อกำหนดความถี่ในการทำงานของซีพียู โดยใช้ HSE = 25 MHz จากภายนอก (ใช้ Crystal Oscillator บนบอร์ด BlackPill STM32F411CEU6) แล้วไปผ่านวงจร PLL ภายใน เพื่อให้ได้ความถี่ 96 MHz

ความถี่ของสัญญาณที่ขาเอาต์พุต ก็ยังคงได้ประมาณ 1000 / (2 * 100 msec) = 5 Hz

#include "stm32f4xx.h"  
#include "stm32f4xx_hal.h"
#define LED_PIN GPIO_PIN_13void SystemClock_Config(void);
void LED_Config(void);
void SysTick_Handler (void) { // ISR for SystemTick interrupt
HAL_IncTick(); // increment system tick counter
}
int main() {
HAL_Init();
SystemClock_Config(); // use HSE (25MHz) + PLL => 96 MHz
LED_Config();
while(1) {
HAL_GPIO_TogglePin( GPIOC, LED_PIN ); // toggle LED pin
HAL_Delay(100);
}
}
void LED_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure;
__GPIOC_CLK_ENABLE();
GPIO_InitStructure.Pin = LED_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
HAL_GPIO_WritePin(GPIOC, LED_PIN, GPIO_PIN_SET);
}
/* System Clock Configuration */
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* Configure Power Regulator Voltage Scaling */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 192;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig( &RCC_OscInitStruct );

/* Select PLL as system clock source and
configure the HCLK, PCLK1 and PCLK2 clocks dividers */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1
| RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig( &RCC_ClkInitStruct, FLASH_LATENCY_3 );
// Note HAL_RCC_OscConfig() and HAL_RCC_ClockConfig() are
// defined in system32f4xx_hal_rcc.c file.
}

การใช้งานบอร์ด STM32F4 Discovery (STM32F407)

เมื่อได้ทดลองใช้งานบอร์ด BlackPill STM32F411CEU6 ไปแล้ว ถ้าจะลองเปลี่ยนมาใช้บอร์ดไมโครคอนโทรลเลอร์ตระกูล STM32F4 เหมือนกัน เช่น STM32F4 Discovery แต่มีวงจร ST-Link Debugger ใส่มาให้แล้ว ไม่ต้องใช้อุปกรณ์มาต่อเพิ่ม

บอร์ดนี้มี LEDs อยู่บนบอร์ด จำนวน 4 ดวง มีสีแตกต่างกัน และตรงกับขาของพอร์ต GPIOD ได้แก่ ขา 12, 13, 14, 15

โค้ดตัวอย่างนี้ สาธิตการทำให้ LED มีสถานะ ON แล้ว OFF เรียงวนไปทีละดวง

#include "stm32f4xx.h" 
#include "stm32f4xx_hal.h"
void LEDs_Config(void); // function prototypevoid SysTick_Handler (void) {
HAL_IncTick(); // increment system ticks (@1kHz rate)
}
int main() {
HAL_Init();
LEDs_Config();
while(1) {
for (int i=0; i < 4; i++ ) {
HAL_GPIO_TogglePin( GPIOD, (uint16_t)(GPIO_PIN_12 << i) );
HAL_Delay(100); // delay for 100 msec
}
}
}
void LEDs_Config(void) {
GPIO_InitTypeDef GPIO_InitStruct;
// turn on clock for GPIO port D
__HAL_RCC_GPIOD_CLK_ENABLE();
// Configure GPIO port D (Pin 12..14) as output pins
GPIO_InitStruct.Pin = (GPIO_PIN_12 | GPIO_PIN_13
| GPIO_PIN_14 | GPIO_PIN_15);
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init( GPIOD, &GPIO_InitStruct );
// drive these output pins to low
HAL_GPIO_WritePin( GPIOD, GPIO_PIN_12 | GPIO_PIN_13
| GPIO_PIN_14 | GPIO_PIN_15, GPIO_PIN_RESET );
}

กล่าวสรุป

เราได้เห็นขั้นตอนการใช้งานซอฟต์แวร์ Kiel MDK / uVision IDE สำหรับการเขียนโค้ดเพื่อนำไปใช้กับบอร์ด STM32F4 และตรวจสอบการทำงานในเบื้องต้นของโค้ด โดยการจำลองการทำงาน หรือทดสอบรันโค้ดโดยใช้ฮาร์ดแวร์จริงได้ผ่านทางอุปกรณ์ ST-Link Debugger

--

--