4.1.1.Giới thiệu
Phần mềm lập trình cho các dòng vi điều khiển STM32 có nhiều chương trình khác nhau, trong đề tài sử dụng phần mềm STM32CubeIDE. Đây là phần mềm miễn phí do hãng ST tạo ra, hỗ trợ cho các dòng vi điều khiển STM32 bao gồm cả chip STM32F4VET6 mà kit thực hành sử dụng, trong phần mềm có tích hợp các công cụ sinh code, soạn thảo, biên dịch và nạp chương trình cho vi điều khiển, rất đơn giản và dễ sử dụng.
Biểu tượng phần mềm STM32CubeIDE sau khi cài đặt xong xuất hiện trong màn hình desktop như sau.
Hình 4.1:Biểu tượng phần mềm STM32CubeIDE
4.1.2.Hướng dẫn sử dụng phần mềm
Phần mềm lập trình cho các dòng vi điều khiển STM32 có nhiều chương trình khác nhau, trong đề tài sử dụng phần mềm STM32CubeIDE. Đây là phần mềm miễn phí do hãng ST tạo ra, trong phần mềm có tích hợp các công cụ sinh code, soạn thảo code và nạp code cho vi điều khiển, rất đơn giản và dễ sử dụng.
Biểu tượng phần mềm STM32CubeIDE sau khi cài đặt xong xuất hiện trong màn hình desktop như sau.
Bước 1: Khởi động phần mềm, giao diện xuất hiện như Hình 4.2. Chọn mục Start New STM32 project.
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 48
Hình 4.2:Giao diện khi khởi động phần mềm
Hình 4.3:Chọn họ vi điều khiển
Bước 2: Giao diện phần chọn Target như hình 4.3. Tìm vi điều khiển STM32F407VET6 bằng cách gõ vào ô tìm kiếm được đánh dấu số 1. Phần đánh dấu số 2 là họ vi điều khiển STM32F4VETx. Chọn “Next” (số 2).
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 49 Bước 3: Hình 4.4 là cửa sổ gõ tên Project, gõ tên và chọn “Finish” theo thứ tự 1, 2 trong hình.
Bước 4: Hình 4.5 là giao diện của file.ioc tức là file cấu hình các chân của vi điều khiển. Ở đây ta để cấu hình mặc định và không chỉnh sửa gì thêm. Tiến hành sinh code bằng cách nhấn Ctr+S và chọn “yes” khi cửa sổ Question hiện lên như Hình 4.6.
Hình 4.4:Gõ tên của Project
Bước 5: Biên dịch cho chương trình như hình 4.7 minh họa. Chọn file main.c theo đường dẫn Core>Src (số 2) thuộc project “cau_hinh” (số 1). Nhấn biểu tượng cây búa (số 3) hình 4.7. Kết quả biên dịch thành công và dung lượng bộ nhớ vi điều khiển sử dụng sẽ hiển thị lần lượt 1,2 trong Hình 4.8.
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 50
Hình 4.5: Giao diện file.ioc cấu hình chân cho vi điều khiển
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 51
Hình 4.7:Cửa sổ soạn thảo chương trình của STM32CubeIDE
Hình 4.8:Cửa sổ hiển thị khi biên dịch xong
Bước 6: Nạp code cho vào bộ nhớ Flash của vi điều khiển bằng công cụ Debugger tích hợp sẵn trong phần mềm STM32CubeIDE, nhấn vào biểu tượng đánh dấu số 3 trong hình 4.8. Sau đó, xuất hiện cửa sổ cấu hình Debugger như hình 4. 9 và chọn “OK”.
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 52
Hình 4.9:Cửa sổ cấu hình Debugger
Hình 4.10:Cửa sổ hiển thị nạp code thành công
4.1.3.Cấu trúc chương trình main.c
Khi sử dụng phần mềm sinh code ta sẽ được phần code như bên dưới. Khi viết chương trình ứng dụng ta sẽ viết các phần vào đúng vị trí comment dành riêng cho nó để khi chinh sửa file cấu hình port.ioc và sinh code lại thì những phần code đó sẽ không bị xóa mất. Sau đây là các mục comment tương ứng với các phần code.
Phần khai báo thư viện /* USER CODE BEGIN Includes */
Phần khai báo define và macro /* USER CODE BEGIN PM */
Phần khai báo biến /* USER CODE BEGIN PV */
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 53 Phần chương trình trước vòng lặp while (1) /* USER CODE BEGIN 2 */
Phần trương trình trong vòng lặp while (1) /* USER CODE BEGIN 3 */
Trong các bài thực hành sẽ chỉ nêu nhưng đoạn code chính để phần trình bày được ngắn gọn và tránh lặp lại, chúng ta phải viết lại bằng cách thêm những đoạn code chính này vào đúng các mục comment dành cho nó.
/* USER CODE BEGIN Header */ /**
************************************************************** * @file : main.c
* @brief : Main program body
************************************************************* * @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics. * All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause *
******************************************* */
/* USER CODE END Header */
/* Includes ---*/
#include "main.h"
/* Private includes ---*/ /* USER CODE BEGIN Includes */
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 54
/* USER CODE END Includes */
/* Private typedef ---*/ /* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ---*/ /* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro ---*/ /* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes ---*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---*/ /* USER CODE BEGIN 0 */
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 55
/**
* @brief The application entry point. * @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration---*/
/* Reset of all peripherals, Initializes the Flash interface and
the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 56 {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration * @retval None
*/
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB busses clocks
*/
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 = 8; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 57 Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType =
RCC_CLOCKTYPE_HCLK|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_DIV4;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } /**
* @brief GPIO Initialization Function * @param None
* @retval None */
static void MX_GPIO_Init(void) {
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 58
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence. * @retval None
*/
void Error_Handler(void) {
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error
return state */
/* USER CODE END Error_Handler_Debug */
}
#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,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 59
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
4.2.HÌNH XUNG CLOCK CHO VI ĐIỀU KHIỂN
Trong các nguồn dao động cung cấp cho STM32 hoạt động bao gồm có : High Speed Internal (HSI : Xung nội tốc độ cao) và High Speed External (HSE : Xung ngoại tốc độ cao).Có nhiều lý do ta sẽ sử dung xung ngoại thay cho xung nội như khi thạch anh ngoài có thể cung cấp dao động cao hơn nguồn xung nội, giúp thu được số lieu chính xác hơn khi giao tiếp với ngoại vi đo nhiệt độ cao hơn rất nhiều so với 25 độ C. Hay như trong một vài trường hợp phải giao tiếp với ngoại vi chỉ có thể hoạt động ở một tần số xác định.
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 60 Bên cạnh nguồn xung tốc độ cao ta còn có Low Speed External (LSE: xung ngoại tốc độ thấp) và Low Speed Internal (LSI: xung nội tốc độ thấp) để điều khiển ngoại vi Real Time Clock (RTC) và Independent Watchdog (IWDT).
Một mạng lưới phức tạp chịu trách nhiệm truyền tín hiệu dao động bên trong STM32 được gọi là Clock Tree. Clock tree sử dung nhiều bộ Phase-Locked Loops (PLL) và Prescalers để tăng / giảm tần số nguồn khi cần thiết.
Lý do chúng ta cần nhiều bộ chia tần số nguồn là để đảm bảo khả năng hoạt động cũng như giảm thiểu năng lượng tiêu thụ ở những chức năng không cần thiết [1].
Cấu hình ClockTree sẽ được thực hiện qua một thiết bị ngoại vi có tên là Reset and Clock Control (RCC) số 2 Hình 4. 11, và nó sẽ đựợc thực hiện qua các bước:
Bước 1: Cấu hình chân dao động cho vi điều khiển.
Trong cửa sổ Pinout & Configuration hình 4. 11, chọn System Core (số 1). Chọn mục RCC (số 2). Trong mục High Speed Clock (HSE), chọn Crystal/Ceramic Resonator (số 3), để lấy xung dao động từ thạch anh 8MHz gắn trên board STM32VE qua 2 chân PH0 và PH1 (số 4).
Hình 4.12:Cấu hình Clock cho vi điều khiển
Bước 2: Cấu hình Clock.
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 61 Số 1: Chọn ngoại tốc độ cao HSE.
Số 2: Chọn tần số thạch anh 8Mhz. Số 3: Chọn bộ chia 8.
Số 4: Chọn bộ nhân 336
Số 5: Chọn PLLCLK để tăng tần số
Số 6: Kết quả sau khi chọn PLLCLK là 168Mhz (tần số tối đa của vi điều khiển) Số 7: Chọn bộ chia 4 cho bus ABH1
Số 8: Chọn bộ chia 4 cho bus ABH2
Sau khi đã cấu hình xong và sinh code tự động ta sẽ được 1 đoạn code cấu hình Clock cho hệ thống như hình 4.13.
Như vậy chúng ta đã cấu hình xong phần Clock dao động cho toàn bộ hệ thống, về sau chúng ta sẽ sử dụng lại file.ioc này và tùy chỉnh thêm cho các module khác như GPIO, ADC, I2C,.. của vi điều khiển. Vì vậy, phần cấu hình xung clock sẽ không đề cập lại trong các bài thực hành và chương trình main.
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 62
4.3.ĐIỀU KHIỂN LED ĐƠN 4.3.1.Sơ đồ phần cứng
Mạch điện giao tiếp vi điều khiển với module led 8 đơn như hình 5.14
Hình 4.14:Sơ đồ nguyên lý giao tiếp vi điều khiển với module 8 led đơn
4.3.2.Cấu hình chân cho vi điều khiển
Module 8 LED đơn giao tiếp trực tiếp với 8 chân của vi điều khiển từ PA0 đến PA7. Cấu hình port trong CubeMX được minh họa như Hình 4.15.
Phần đánh số 1 là chọn chức năng GPIO_Output cho chân PA7, tương tự cho các chân PA0 đến chân PA6.
Phần đánh số 2 chọn mục GPIO để cấu hình chi tiết cho từng chân. Phần đánh số 3 chọn các mục Parameter Setting như trong Hình 4.15.
Vì đã cấu hình xung clock cho hệ thống ở phần trước nên ta không cấu hình lại các thông số trong mục Clock Configuration nữa.
Sau khi cấu hình xong trong CubeMX ta nhấn Ctrl + S để sinh code tự động. Hình 4.16 là phần code được sinh ra trong chương trình main tương ứng với các mục đã chọn trong CubeMX.
Khi viết 1 chương trình ứng dụng trong file main.c ta không cần khai báo lại cấu hình chân. Và để đơn giản trong việc trình bày code sinh viên thực hiện đề tài chỉ nêu các dòng code chính mà bỏ qua việc trình bày lại phần cấu hình chân cho vi điều khiển.
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 63
Hình 4.15:Cấu hình port cho 8 led đơn trong CubeMX
Hình 4.16:Phần code được sinh ra từ CubeMX
4.3.3.Các hàm sử dụng
Hàm thứ 301: là hàm xuất dữ liệu 1 byte ra module 8 led đơn
void xuat_8led_1byte(uint8_t byte) {
GPIOA->ODR = byte;
BỘ MÔN ĐIỆN TỬ CÔNG NGHIỆP – Y SINH 64 Hàm này có chức năng xuất 1 byte dữ liệu ra module 8 led. Thanh ghi ODR có chưng năng xuất dữ liệu trực tiếp ra các port GPIO.
Hàm thứ 302: là hàm xuất dữ liệu 2 16 bit ra module 32 led đơn
void xuat_8led_2x4bit(uint8_t YH,uint8_t YL) {
uint8_t YHL;
YH=(YH<<4)&0x00f0; YL=YL&0x000f; YHL=YH|YL;
GPIOA->ODR = YHL;
}
Hàm này có chức năng xuất 4bit cao và 4 bit thấp ra module 8 led.
Các hàm này được lưu trong file thư viện TV_DATN_1.c và TV_DATN_1.h
Khi sử dụng thư viện này ta tiến hành copy TV_DATN_1.c vào thư mục Src và copy TV_DATN_1.h và thư mục Inc của Project.
4.3.4.Bài tập mẫu
Phần này thực hành các bài điều khiển led dùng vòng lặp for, các chương trình đơn giản dễ hiểu.
a. Mục đích: biết cách viết chương trình điều khiển led đơn chớp tắt.