Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

Bài 2.

Lập trình ngắt GPIO, thiết bị hiển thị


Mục đích.
Trang bị cho sinh viên các kiến thức về tổ chức ngắt trong ARM STM32. Cách lập
trình ứng dụng sử dụng ngắt ngoài để thiết kế ứng dụng.
Yêu cầu.
Sinh viên nắm được:
- Các nguyên nhân gây ra ngắt
- Cách lập trình một chương trình có sử dụng ngắt.
1. Giới thiệu nguyên nhân xảy ra ngắt ngoài
- Ngắt ngoài xảy ra khi có sườn âm hoặc sườn dương hoặc có sự chuyển mức logic
đến chân EXTI của STM32.
External Interrupt Mode with Rising
GPIO_MODE_IT_RISING
edge trigger detection
GPIO_MODE_IT_FALLING External Interrupt Mode with Falling
edge trigger detection
External Interrupt Mode with
GPIO_MODE_IT_RISING_FALLING
Rising/Falling edge trigger detection
- Thứ tự ưu tiên ngắt (khi các ngắt tác động đồng thời):

o Có 5 nhóm ưu tiên ngắt, với 4 bit thiết lập ưu tiên

- Các hàm điều khiển hoạt động ngắt trong API HAL
• HAL_NVIC_SetPriorityGrouping - Hàm thiết lập nhóm ưu tiên
• HAL_NVIC_SetPriority - Hàm thiết lập mức ưu tiên
• HAL_NVIC_EnableIRQ
- Hàm cho phép ngắt
• HAL_NVIC_DisableIRQ
• HAL_NVIC_GetPriorityGrouping
• HAL_NVIC_GetPriority
• HAL_NVIC_SetPendingIRQ
• HAL_NVIC_GetPendingIRQ
• HAL_NVIC_ClearPendingIRQ
• HAL_NVIC_GetActive
• HAL_EXTI_SetConfigLine
• HAL_EXTI_GetConfigLine
• HAL_EXTI_ClearConfigLine
• HAL_EXTI_RegisterCallback
• HAL_EXTI_GetHandle

2. Lập trình điều khiển sử dụng ngắt ngoài

2.1 Các bước lập trình với công cụ STM CubeMX

a. Các bước lập trình

Bước 1. Thiết lập hệ thống


- Thiết lập xung nhịp hệ thống : SystemClock_Config();
Bước 2. Thiết lập cho các GPIO

- Cho phép GPIO – AFIO tương ứng hoạt động bằng hàm:
__HAL_RCC_GPIOx_CLK_ENABLE();

Bước 3. Cấu hình chân EXTI


- Chân ngắt phải thiết lập chiều vào dữ liệu.
- Lựa chọn nguyên nhân gây ra ngắt.

GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
Bước 4. Cấu hình NVIC:
- Bật kênh ngắt trong NVIC: HAL_NVIC_EnableIRQ(EXTI0_IRQn);
- Cấu hình mức độ ưu tiên: HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
- Cấu hình nhóm ưu tiên:
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
Bước 5. Chờ khi có ngắt.
- Chờ ngắt trong chương trình chính.
- Viết chương trình con phục vụ ngắt, trong file “stm32f1xx_it.c” hoặc trong “main.c”

void EXTI0_IRQHandler(void) // Ví dụ ngắt GPIO Line 0


{
B1. Xóa cờ ngắt bằng hàm :
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);
B2. Kiểm tra điều kiện khi xảy ra ngắt GPIO: ví dụ: PA0
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0)
{ //thực hiện lệnh }
B3. Xử lý yêu cầu khi có ngắt:
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
b. Thiết lập trên STM Cube Mx
Bước 1. Cấu hình chân GPIO là ngắt ngoài (ví dụ trên chân PA0)
Thiết lập GPIO_EXTI0 trên chân

PA0
Bước 2. Lựa chọn nguyên nhân gây ra ngắt ngoài

Lựa chọn GPIO

Thiết lập nguyên nhân gây ngắt :


Thiết lập nguyên nhân gây ngắt : lựa chọn ngắt sườn âm trên PA0
External Interrupt Mode with Falling edge trigger detection

Thiết lập nguyên nhân gây ngắt : lựa chọn Pull-up

Bước 3. Thiết lập ưu tiên ngắt


Lựa chọn NVIC

Lựa chọn nhóm ưu tiên NVIC


Lựa chọn mức ưu tiên: Preemption - Sub

Lựa chọn chân chiều vào, chiều ra, mode. Thiết lập các thông số trên STM32CubeMX
như trong hướng dẫn lập trình với GPIO

Sau đó chọn GENERATE CODE để tạo file Code

2.2 Lập trình với ngắt ngoài


- Khung của chương trình sử dụng ngắt
#include "main.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();

while (1)
{}
}
static void MX_GPIO_Init(void)
{ GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
//= Chương trình con phục vụ ngắt
void EXTI0_IRQHandler(void)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0)//Khi có ngắt
{
}
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
2.4 Ví dụ
Ví dụ 1. Viết chương trình điều khiển LED1 nhấp nháy liên tục, khi nhấn nút PB1

LED1 tắt, LED2 nhấp nháy 10 lần.


#include "main.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (1)
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_10, GPIO_PIN_SET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_10, GPIO_PIN_RESET);
HAL_Delay(100);
}
}

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();
__HAL_RCC_GPIOB_CLK_ENABLE();

HAL_GPIO_WritePin(GPIOA,GPIO_PIN_10|GPIO_PIN_15,
GPIO_PIN_RESET);
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_10| GPIO_PIN_15;


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);

HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}

void EXTI0_IRQHandler(void){
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0){
for(int i=0;i<10;i++){
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_15, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_15, GPIO_PIN_RESET);
HAL_Delay(500);
}
}
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
Ví dụ 2. Lập trình đếm sản phNm sử dụng ngắt ngoài EXTI0, số sản phNm được
hiển thị trên 1 led 7 thanh.
#include "main.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
int dem;
char ma_led[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
0x82,0xf8,0x80,0x90};
void hienthi(unsigned char dulieu)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,dulieu&0x01);//a
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9, (dulieu>>1)&0x01);//b
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,(dulieu>>2)&0x01);//c
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,(dulieu>>3)&0x01);//d
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,(dulieu>>4)&0x01);//e
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,(dulieu>>5)&0x01);//f
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14,(dulieu>>6)&0x01);//g
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,(dulieu>>7)&0x01);//dp
}
int main(void)
{
HAL_Init(); SystemClock_Config(); MX_GPIO_Init();
while (1)
{
hienthi(ma_led[dem]); HAL_Delay(500);
}
}
- Chương trình con viết trong file “stm32f1xx_it.c”
extern int dem; //Khai báo biến bên ngoài

void EXTI0_IRQHandler(void)
{
if(HAL_GPIO_ReadPin(GPIOA,PB1_Pin)==0)
{
dem=dem+1;//dem++
}
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
Chú ý: Các hàm khởi tạo, thiết lập chiều dữ liệu giống như ví dụ 1

Ví dụ 3. Viết chương trình điều khiển LED1 nhấp nháy liên tục. Khi nhấn nút PB1
LED1 tắt, LED2 nhấp nháy 5 lần. Khi nhấn PB2 LED1 tắt, LED3 nhấp nháy 10
lần. Thiết lập ngắt với nút PB1 ưu tiên cao, ngắt với nút PB2 ưu tiên thấp.
#include "main.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
#include "main.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
int main(void){
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (1){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);
HAL_Delay(200);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
HAL_Delay(200);
}}
- Thiết lập ưu tiên ngắt:
HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);

HAL_NVIC_SetPriority(EXTI1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI1_IRQn);
- Chương trình con viết trong file “stm32f1xx_it.c”
void EXTI0_IRQHandler(void){
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)==0){
for(int i=0;i<5;i++){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
HAL_Delay(1000);}}
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
void EXTI1_IRQHandler(void){
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1)==0){
for(int i=0;i<10;i++){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
HAL_Delay(1000);}}
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
}
2.5. Bài tập.
1. Viết chương trình sử dụng ngắt ngoài EXTI1 điều khiển 8 LED theo quy luật.
Khi nhấn KEY1 một lần LED1 sáng các LED khác tắt, nhấn KEY1 2 lần LED1,
LED2 sáng các LED khác tắt… Nhấn KEY1 8 lần cả 8 LED đều sáng.
2. Viết chương trình sử dụng ngắt ngoài EXTI0 điều khiển đếm số lần nhấn KEY1
và hiển thị số lần nhấn trên 4 LED (LED1- LED4) dưới dạng số nhị phân (Giả
thiết: số lần nhấn <=15).
3. Lập trình đếm sản phNm sử dụng ngắt ngoài EXTI1, số sản phNm được
hiển thị trên 2 led 7 thanh.
4. Lập trình đếm sản phNm sử dụng ngắt ngoài EXTI2, số sản phNm được
hiển thị trên 4 led 7 thanh.
5. Lập trình sử dụng ngắt ngoài EXTI0, EXTI1 theo yêu cầu:
- Điều khiển LED1 nhấp nháy liên tục.
- Khi nhấn nút kết nối với chân EXTI0 – LED1 tắt. LED 7 thanh (7SEG1)
hiển thị từ 0 đến 5.
- Khi nhấn nút kết nối với chân EXTI1 – LED1 tắt. LED 7 thanh (7SEG2)
hiển thị từ 0 đến 8.
- Thiết lập ngắt EXTI0 ưu tiên cao hơn ngắt EXTI1.
6. Lập trình sử dụng ngắt ngoài mô phỏng bãi đỗ xe: Cảm biến vào CB1 nối với
chân PB0 ; Cảm biến ra CB2 nối với chân PB1.
-Hiển thị số xe vào, số xe ra, số xe có trong bãi lên LCD 16x2 theo yêu cầu
như sau:
7. Lập trình sử dụng ngắt ngoài mô phỏng bãi đỗ xe: Cảm biến vào CB1 nối với chân
PB0 ; Cảm biến ra CB2 nối với chân PB1.
-Hiển thị số xe vào, số xe ra, số xe có trong bãi lên 6 Led 7 thanh theo yêu
cầu như sau:
+ Số xe vào hiển thị trên 2 LED hàng Chục, hàng Đơn vị.
+ Số xe ra hiển thị trên 2 LED hàng Trăm nghìn, hàng Chục nghìn.
+ Số xe có trong bãi hiển thị trên 2 LED hàng Nghìn, hàng Trăm.

You might also like