Bài thực hành 1 với nội dung Lập trình điều khiển vào ra cho GPIO. giúp các bạn làm quen với phần mềm, sơ đồ chân và các lệnh điều khiển vào ra căn bản và những bài tập giúp các bạn luyện tập thành thạo.
BÀI LẬP TRÌNH ĐIỀU KHIỂN VÀO/ RA GPIO Giới thiệu sơ đồ nguyên lý Kit ARM STM32F103C8T6 - Sơ đồ chân Hình 1.1 Sơ đồ chân KIT STM32F103C8T6 - Khối Led đơn – PC13 Hình 1.2 Mạch Led đơn - Muốn điều khiển Led sáng – xuất mức Logic 0, ngược lại Led tắt – Xuất mức Logic - Khối nút nhấn lắp thêm, mắc hình 1.2 +3.3V R1 10K INPUT PB1 C1 104 GND Hình 1.2 Mạch nút nhấn - Khi đọc nút nhấn cần thiết lập trở kéo lên bên chíp: GPIO_InitStruct.Pull = GPIO_PULLUP; Các hàm điều khiển hoạt động vào/ra - Các hàm điều khiển hoạt động vào API HAL • HAL_GPIO_ReadPin - Hàm đọc liệu • HAL_GPIO_WritePin - Hàm ghi liệu • HAL_GPIO_TogglePin - Hàm đảo mức logic • HAL_GPIO_LockPin • HAL_GPIO_EXTI_IRQHandler • HAL_GPIO_EXTI_Callback • HAL_GPIO_Init • HAL_GPIO_DeInit - Câu lệnh xuất liệu theo PORT, ví dụ với PORT B: GPIOB->ODR=0x0000;//PB0 ÷ PB15 mức logic - Câu lệnh đọc liệu theo PORT, ví dụ với PORT B: X= GPIOB->IDR; Thiết kế ứng dụng hoạt động vào/ra 3.1 Các bước lập trình với hoạt động vào sử dụng STM32CubeMX Cấu hình cho xung nhịp hệ thống Cho phép xung nhịp PORT GPIO Thiết lập chiều chân GPIO Cấu hình cho chân GPIO Viết thuật tốn điều khiển GPIO - Cấu hình cho xung nhịp hệ thống : o SystemClock_Config(); Ví dụ : void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; //Lựa chọn nguồn xung cho tạo dao động RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {Error_Handler();} //Thiết lập hệ số chia tần cho ngoại vi RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler();} } Cho phép xung nhịp PORT GPIO o HAL_RCC_GPIOx_CLK_ENABLE(); o Ví dụ : HAL_RCC_GPIOB_CLK_ENABLE();//Cho phép PORTB - Thiết lập chức chân GPIO GPIO_MODE_INPUT Input Floating Mode GPIO_MODE_OUTPUT_PP Output Push Pull Mode GPIO_MODE_OUTPUT_OD Output Open Drain Mode GPIO_MODE_AF_PP Alternate Function Push Pull Mode GPIO_MODE_AF_OD Alternate Function Open Drain Mode GPIO_MODE_ANALOG Analog Mode GPIO_MODE_IT_RISING External Interrupt Mode with Rising edge trigger detection GPIO_MODE_IT_FALLING External Interrupt Mode with Falling edge trigger detection GPIO_MODE_IT_RISING_FALLING External Interrupt Mode with Rising/Falling edge trigger detection GPIO_MODE_EVT_RISING External Event Mode with Rising edge trigger detection GPIO_MODE_IT_RISING_FALLING External Interrupt Mode with Rising/Falling edge trigger detection GPIO_MODE_EVT_RISING External Event Mode with Rising edge trigger detection GPIO_MODE_EVT_FALLING External Event Mode with Falling edge trigger detection GPIO_MODE_EVT_RISING_FALLING External Event Mode with Rising/Falling edge trigger detection - Cấu hình chân GPIO : + Trở kéo GPIO_NOPULL No Pull-up or Pull-down activation GPIO_PULLUP Pull-up activation GPIO_PULLDOWN Pull-down activation + Tốc độ GPIO_SPEED_FREQ_LOW Low speed GPIO_SPEED_FREQ_MEDIUM Medium speed GPIO_SPEED_FREQ_HIGH High speed - Cấu hình chân GPIO – (thiết lập chân GPIO có chiều vào): Ví dụ chân PA0: GPIO_InitStruct.Pin = GPIO_PIN_0;//Chân GPIO_InitStruct.Mode = GPIO_MODE_INPUT;//Chiều vào GPIO_InitStruct.Pull = GPIO_PULLUP;//Trở kéo lên HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - Cấu hình chân GPIO – (thiết lập chân GPIO có chiều ra): Ví dụ chân PB9: GPIO_InitStruct.Pin = GPIO_PIN_9;//Chân GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//chiều PUSH PULL GPIO_InitStruct.Pull = GPIO_NOPULL;//Không kéo trở GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;//Tần số thấp HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - Xuất liệu o HAL_GPIO_WritePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) ; o Hoặc : GPIOB->ODR=data; Ví dụ: Xuất mức logic chân PB9 - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET); - hoặc: GPIOB->ODR=0x0200;//0b0000 0010 0000 0000 - Đảo mức tín hiệu o HAL_GPIO_TogglePin(GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin); Ví dụ: Đảo mức logic chân PA0 - HAL_GPIO_TogglePin (GPIOA, GPIO_PIN_0); - Nhập liệu o HAL_GPIO_ReadPin(GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin) Ví dụ: Đọc liệu chân PA0 X = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0); 3.2 Khung chương trình lập trình hoạt động vào #include "main.h" void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void) { SystemClock_Config(); MX_GPIO_Init(); while (1) {} } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler();} RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = LED1_Pin|LED2_Pin|LED3_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void Error_Handler(void){ disable_irq();while (1){}} #ifdef USE_FULL_ASSERT #endif /* USE_FULL_ASSERT */ 3.3 Ví dụ Ví dụ 1: Lập trình điều khiển LED –(kết nối với chân PA0) sáng #include "main.h" int main(void) { SystemClock_Config(); MX_GPIO_Init(); while (1) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); } } Ví dụ 2: Lập trình điều khiển LED –(kết nối với chân PA0) nhấp nháy với chu kì 1s #include "main.h" int main(void) { SystemClock_Config(); MX_GPIO_Init(); while (1) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); HAL_Delay(500); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); HAL_Delay(500); } } Ví dụ 3: Lập trình điều khiển nhấn nút Select (kết nối với chân PA11) LED (kết nối với chân PA0) sáng, không nhấn LED tắt #include "main.h" int main(void) { SystemClock_Config(); MX_GPIO_Init(); while (1){ if(HAL_GPIO_ReadPin(GPIOA, GPIO_Pin_11)==0) HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); else HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_RESET); /*Configure GPIO pins : PA11*/ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pins : PA0*/ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } Ví dụ 4: Lập trình điều khiển mạch Led (A Chung) hiển thị từ đến Mạch điện hình sau: - Sử dụng mã Led từ đến cách khai báo mảng: char ma_led[]={0x00c0,0x00f9,0x00a4,0x00b0,0x0099, 0x0092,0x0082,0x00f8,0x0080,0x0090}; - Cách 01: Viết chương trình chuyển từ byte sang bit từ mảng ma_led[]sang chân Vi điều khiển kết nối với a,b,c,d,e,f,dp Led void hienthi_7seg(unsigned char data) { HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7, } int dem; int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); while (1) data&0x01);//a (data>>1)&0x01);//b (data>>2)&0x01);//c (data>>3)&0x01);//d (data>>4)&0x01);//e (data>>5)&0x01);//f (data>>6)&0x01);//g (data>>7)&0x01);//dp { hienthi_7seg(ma_led[dem%10]); HAL_Delay(1000); dem++; } } - Cách 02: Sử dụng câu lệnh GPIOB->ODR xuất liệu int dem; int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); while (1) { GPIOB->ODR =ma_led[dem%10]; HAL_Delay(1000); dem++; } } Chú ý: Sinh viên cần cấu hình chiều liệu chân điều khiển Led Ví dụ 5: Lập trình điều khiển mạch Led (A Chung) hiển thị số có chữ số Mạch điện hình sau: - Sử dụng phương pháp quét led để điều khiển Led thanh: - Cách 01: Viết chương trình chuyển từ byte sang bit từ mảng ma_led[]sang chân Vi điều khiển kết nối với a,b,c,d,e,f,dp Led void hienthi_7seg(unsigned char data) { HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6, HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7, data&0x01); (data>>1)&0x01); (data>>2)&0x01); (data>>3)&0x01); (data>>4)&0x01); (data>>5)&0x01); (data>>6)&0x01); (data>>7)&0x01); } int dem; int main(void) { HAL_Init();SystemClock_Config();MX_GPIO_Init(); dem=12; while (1) { //Hiển thị Led hàng chục; HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8, GPIO_PIN_RESET);//0 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9, GPIO_PIN_SET);//1 hienthi_7seg(ma_led[dem/10]); HAL_Delay(2); //Hiển thị Led hàng đơn vị; HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8, GPIO_PIN_SET);//1 HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9, GPIO_PIN_RESET);//0 hienthi_7seg(ma_led[dem%10]); HAL_Delay(2); } } - Cách 02: Sử dụng câu lệnh GPIOB->ODR xuất liệu int dem; int main(void) { HAL_Init();SystemClock_Config();MX_GPIO_Init(); dem=12; while (1) { GPIOB->ODR=ma_led[dem/10]|0x0200;//0b0000 0010 0000 0000 HAL_Delay(2); GPIOB->ODR=ma_led[dem%10]|0x0100;//0b0000 0001 0000 0000 HAL_Delay(2); }} Chú ý: Sinh viên cần cấu hình chiều liệu chân điều khiển Led 4 Bài tập: (Sinh viên tự chọn chân LED KEY) Viết chương tình hiển thị LED chẵn lẻ sáng nhấp nháy (LED 1,3,5,7 sáng, LED 2,4,6,8 Tắt ngược lại) 2.Viết chương trình điều khiển LED sáng nhấn KEY1 LED tắt Viết chương trình điều khiển LED theo quy luật Khi nhấn KEY1 lần LED1 sáng LED khác tắt, nhấn KEY1 lần LED1, LED2 sáng LED khác tắt… Nhấn KEY1 lần LED sáng Viết chương trình điều khiển đếm số lần nhấn KEY2 hiển thị số lần nhấn LED (LED4- LED8) dạng số nhị phân (Giả thiết: số lần nhấn >1)&0x01);//b (data>>2)&0x01);//c (data>>3)&0x01);//d (data>>4)&0x01);//e (data>>5)&0x01);//f (data>>6)&0x01);//g (data>>7)&0x01);//dp { hienthi_7seg(ma_led[dem%10]);... HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7, data&0x01); (data>>1)&0x01); (data>>2)&0x01); (data>>3)&0x01); (data>>4)&0x01); (data>>5)&0x01); (data>>6)&0x01); (data>>7)&0x01); } int dem; int main(void) { HAL_Init();SystemClock_Config();MX_GPIO_Init();... GPIOB->ODR=ma_led[dem/10]|0x0200;//0b0000 0010 0000 0000 HAL_Delay(2); GPIOB->ODR=ma_led[dem%10]|0x0100;//0b0000 0 001 0000 0000 HAL_Delay(2); }} Chú ý: Sinh viên cần cấu hình chiều liệu chân điều khiển Led 4 Bài tập: (Sinh