Cài đặt IDE - Viết chương trình đầu tiên

Chương trình đầu tiên với STM32

Phần mềm

Để bắt đầu vào làm việc với dòng STM32, ngoài công cụ hỗ trợ cấu hình là STM32CubeMX thì còn có phần mềm lập trình và biên dịch nữa.

Các phần mềm hỗ trợ viết code và biên dịch nổi tiếng như Keil C, IAR, Cocos Code IDE… (Các bạn có thể dễ dàng tìm và tải về các phiên bản cũ mới của các phần mềm này trên Internet - Hiện tôi dùng Keil C ver 5).

Phần cứng

Hiện tại phần cứng của tôi gồm có:

Mạch nạp ST-Link v2 - tải về ST-Link Driver.

Mạch nạp ST-Link v2

STM32F103RCT6 Development Board

ARM Cortex M3 STM32F103RBT6 MINI Development Board

Nối mạch nạp với board phát triển thông qua 4 dây: Vcc, GND, SWCLK, SWDIO

Trong đó SWCLK nối đến PA13, SWDIO nối đến PA14. (Tham khảo tại STM32F_Datasheet trang 35)

Tải về Sơ đồ nguyên lý Board STM32F103R.

Khởi động STM32CubeMX, cấu hình lựa chọn MCU STM32F103RCT6, chọn chế độ GPIO Output cho 3 chân PB0, PB1, PB2.

Cấu hình chân MCU

Xuất mã nguồn sau khi cấu hình từ STM32CubeMX với tùy chọn xuất ra Project cho Keil C v5. Trong folder xuất ra đã bao gồm các API cần thiết, phần lõi, các thư viện liên quan.

Ta được Folder như dưới đây.

Thư mục chứa Project

File TestGPIO.uvprojx là file Project của Keil C, doubleclick vào file này để bắt đầu mở project này bằng chương trình Keil C. Sau khi project đã được load thì bạn cũng không cần phải làm gì khác ngoài việc code và nhấn nút biên dịch - nạp.

Chương trình Keil C mở lên có giao diện như hình sau:

Mở project với KeilC

Mã nguồn chúng ta sẽ viết tại file main.c này.

Tại đây chúng ta có thể thấy, toàn bộ quá trình khởi tạo ngoại vi đã được phần mềm tự động hóa làm hết, chúng ta chỉ việc bắt tay vào viết code cho chương trình.

Code chương trình nhấp nháy 3 led tại PB0, PB1, PB2:

#include "stm32f1xx_hal.h"

void SystemClock_Config(void);
static void MX_GPIO_Init(void);

uint32_t delay = 0;


int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();

  while (1)
  {

    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1 | GPIO_PIN_2); //Blink 3 Led
    for(delay = 0; delay <1000000; delay++);

  }
}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);

  __HAL_RCC_AFIO_CLK_ENABLE();

}

/** Configure pins as
        * Analog
        * Input
        * Output
        * EVENT_OUT
        * EXTI
*/
void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __GPIOB_CLK_ENABLE();

  /*Configure GPIO pins : PB0 PB1 PB2 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */

}

#endif

/**
  * @}
  */

/**
  * @}
*/

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Có nhiều cách để tạo ra 1 khoảng thời gian trễ bằng cách dùng vòng lặp, hoặc được hỗ trợ trực tiếp từ firmware bằng hàm:

HAL_Delay(300); //Trễ 300 nhịp CPU

Và đảo trạng thái của chân GPIO sau một khoảng thời gian định sẵn, việc đảo trạng thái được thực hiện bằng:

HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1 | GPIO_PIN_2);

Nhìn câu lệnh rất dễ hiểu đúng không?

GPIO trên STM32 được hỗ trợ từ firmware bởi thư viện stm32f1xx_hal_gpio thông qua các hàm trừu tượng với các tham số đi kèm:

Các bạn có thể tham khảo nhanh các hàm và các tham số cần thiết được hỗ trợ bởi firmware bằng cách click chọn thẻ Functions trong khung phần mềm Keil C.

Chi tiết các hàm hỗ trợ

Trong quá trình viết code, nếu không nhớ rõ lệnh thì Keil C cũng hỗ trợ nhắc lệnh thông qua tổ hợp phím Ctrl+Space.

Build and Compile

Để Build thì nhấn nút có đánh dấu màu xanh lá cây, nhấn nút đánh đấu đỏ để biên dịch và nạp chương trình cho MCU.