STM32F4 HAL Ngắt ngoài

Thảo luận trong 'STM32' bắt đầu bởi VuPhat.MCA, 8/5/19.

  1. VuPhat.MCA

    VuPhat.MCA New Member

    Trong chip STM32F407 có tất cả 23 dòng ngắt ngoài được điều khiển bởi bộ EXTI (External interrupt/event controller) trong đó có 16 dòng ngắt từ 0 đến 15 được sử dụng trên các chân GPIO, và 7 dòng ngắt từ 16 đến 22 được kết nối với đầu ra PVD, sự kiện báo thức RTC, sự kiện đánh thức Ethernet, ... Sau đó được đưa tới bộ điều khiển véc tơ lồng nhau NVIC (Nested vectored interrupt controller), tại NVIC chúng ta có thể lập trình mức độ ưu tiên ngắt, kiểm soát nguồn, ... Nhớ rằng bên cạnh ngắt ngoài EXTI, các véc tơ ngắt của hệ thống như UART, DMA, ADC, SPI, Timer, ... đều được điều khiển bởi NVIC.

    [​IMG]

    Mỗi dòng ngắt có số tương ứng với dòng chân GPIO sử dụng, ví dụ PA0, PB0, PC0, PD0, ... được kết nối với dòng ngắt 0 (line0), PA1, PB1, PC1, PD1, ... được kết nối với dòng ngắt 1, tóm lại tất cả các chân cùng số đều được nối với dòng cùng số. Các chân ngắt trên các dòng ngắt đều được lựa chọn thông qua các bit EXTIn trên các thanh ghi từ SYSCFG_EXTICR1 đến SYSCFG_EXTICR4.

    [​IMG]

    Tại một dòng ngắt nhất định chúng ta chỉ sử dụng được trên chỉ một chân GPIO mà thôi, ví dụ ta không thể dùng 2 ngắt PA0, PB0 trên dòng ngắt 0 cùng lúc được mà chỉ được dùng PA0 hoặc PB0.

    Mỗi dòng ngắt được kích hoặt tại cạnh lên (rising), cạnh xuống (falling), hoặc cả cạnh lên/xuống (rising/falling).

    KẾT NỐI NGOẠI VI

    Bài này chúng ta sử dụng chân ngắt ngoài tại chân PA0 và một màn hình LCD HD44780 để hiển thị giá trị đếm mỗi khi có ngắt line0 xảy ra, chúng được kết nối như sau:

    [​IMG]

    LCD HD44780 được kết nối với 7 chân PD0, PD1, PD2, PD4, PD5, PD6, PD7, cách giao tiếp đã được giới thiệu trong bài trước, vì thế chúng ta chỉ cần sử dụng luôn thư viện trong bài này mà thôi.

    SINH CODE VỚI STM32CUBEMX

    Tạo project mới

    Đầu tiên ta mở STM32CubeMX lên, sau đó tạo mới một Project bằng cách chọn File > New Project ...

    Cửa sổ New Project hiện lên, vào Series để lọc chip theo seri, sau đó chọn STM32F4.

    Trong MCUs list, chọn chip STM32F407VG, sau đó nhấn Start project để bắt đầu tạo project mới.

    Cấu hình RCC

    Với bài này ta cấu hình các thông số như sau: High Speed Clock = Crystal/Ceramic Resonators, Input frequency = 8, HSE, /M = 8, *N = 336, /P = 2, PLLCLK, AHB1 Prescale = 4AHB2 Prescale = 2.

    Cấu hình

    Trong bản đồ chân, cấu hình các chân PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7 chức năng là GPIO_Output, PA0 có chức năng là GPIO_EXTI0.

    Trong Configuration, nhấp chọn GPIO. Trong bài này chúng sẽ có các thông số cấu hình như sau:

    • PA0-WKUP
      • GPIO Mode: Có 6 chế độ ngắt ngoài là: External Interrupt Mode with Rising edge trigger detection (Chế độ ngắt ngoài với kích hoạt phát hiện ở cạnh lênh), External Interrupt Mode with Falling edge trigger detection (Chế độ ngắt ngoài với kích hoạt phát hiện ở cạnh xuống), External Interrupt Mode with Rising/Falling edge trigger detection (Chế độ ngắt ngoài với kích hoạt phát hiện ở cạnh lên/xuống), External Event Mode with Rising edge trigger detection (Chế độ sự kiện ngoài với kích hoạt phát hiện ở cạnh lênh), External Event Mode with Falling edge trigger detection (Chế độ sự kiện ngoài với kích hoạt phát hiện ở cạnh xuống), External Event Mode with Rising/Falling edge trigger detection (Chế độ sự kiện ngoài với kích hoạt phát hiện ở cạnh lênh/xuống). Sự kiện sẽ khác với ngắt ngoài, chúng chỉ có nhiệm vụ đánh thức lõi hoạt động. Trong bài này khi nút được nhấn PA0 sẽ có sự chuyển mức logic từ thấp lên mức cao, như vậy ta sử dụng chế độ External Interrupt Mode with Rising edge trigger detection để phát hiện sự chuyển mức logic này
      • GPIO Pull-up/Pull-down: No pull-up an no pull-down
    • PD0, PD1, PD2, PD4, PD5, PD6, PD7
      • GPIO output level: Low
      • GPIO mode: Output Push Pull
      • GPIO Pull-up/Pull-down: No pull-up an no pull-down
      • Maxium output speed: Very high
    Chuyển qua NVIC, ở hàng Enabled tích chọn EXTI line0 interrupt để cho phép ngắt ngoài trên dòng 0.

    Nhấn Apply, sau đó nhấn OK để xác nhận hoàn tất cấu hình GPIO.

    Nhấp chọn nút NVIC, tại đây chúng ta chọn chọn EXTI line0 interrupt, mặc định chúng đã được tích Enabled với mức độ ưu tiên bằng đều bằng 0.

    Nhấn Apply, sau đó nhấn OK để xác nhận hoàn tất cấu hình NVIC.

    [​IMG]

    Sinh code

    Vào Project > Generate code để sinh code tự động, tại đây cửa sổ Project Settings hiện lên.

    Trong Project, chúng ta chọn đường dẫn để lưu project (Project Location) bằng cách nhấp chọn Browse, sau đó đặt tên cho project (Project Name) và cuối cùng là chọn công cụ phát triển tích hợp(Toolchain / IDE) là MDK-ARM V5 (lựa chọn sở thích của mỗi người).

    Trong Code Generator, tích chọn Add necessary library files as refernce in the toolchain project configuration file để thêm các tệp cần thiết để sử dụng với công cụ phát triển tích hợp.

    Sau đó chọn OK để hoàn thành sinh code tự động.

    Cuối cùng, chọn Open Project để mở project với MDK-ARM V5.

    LẬP TRÌNH VỚI MDK-ARM V5

    Có thể vào thư mục lưu project để mở lại nếu chẳng may tắt đi. Trong MDK-ARM V5, chọn Project > Options for Target 'ten_project' ... để cấu hình cho project.

    Trong cửa sổ Options for Target 'ten_project' nhấp chọn Debug, chọn mạch nạp là ST-Link Debugger. Tiếp tục chọn Settings. Một cửa sổ mới hiện lên, tiếp tục chọn Flash Download, tích chọn Reset and Run để khi sử nạp chương trình board STM32F4 Discovery sẽ tự Reset và chạy lại. Sau đó nhấn OK 2 lần để hoàn tất.

    Sao chép hai tệp lcd.hlcd.c trong bài giao tiếp với LCD HD44780 vào hai thư mục \Inc\Src tương ứng.

    Quay trở lại MDK-ARM V5, để sử dụng thư viện LCD các bạn mở rộng project, sau đó nhấp chuột phải vào Application/User > Add Existing Files to Group 'Application/User'..., trỏ đến đường dẫn \Src và thêm tệp lcd.c vào project hiện hành.

    Mở tệp main.c, thêm đoạn code sau ngay dưới /* USER CODE BEGIN Includes */:
    Mã:
    #include "lcd.h"
    
    Tiếp tục thêm đoạn code sau ngay dưới /* USER CODE BEGIN 0 */:
    Mã:
    uint16_t cnt = 0;
    
    Tiếp tục thêm đoạn code sau ngay dưới /* USER CODE BEGIN 1 */:
    Mã:
    char str[17];
    
    Tiếp tục thêm đoạn code sau ngay dưới /* USER CODE BEGIN 2 */:
    Mã:
    LCD_Init();
    
    Tiếp tục thêm đoạn code sau ngay dưới /* USER CODE BEGIN 3 */:
    Mã:
    sprintf(str, "%d", cnt);
    LCD_SetPos(0, 0);
    LCD_String(str);
    
    Tiếp tục thêm đoạn code sau ngay dưới /* USER CODE BEGIN 4 */:
    Mã:
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    {
      if (GPIO_Pin == GPIO_PIN_0)
      {
       if (++cnt > 9999) cnt = 0;
      }
      while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0));
    }
    
    Build và nạp chương trình chúng ta thấy mỗi khi nhấn nút USER giá trị hiển thị trên màn hình LCD sẽ được tăng thêm. do tín hiệu từ nút nhấn bị dao động dẫn đễn sẽ có trường hợp hai ba ngắt xảy ra liên tục làm cho giá trị đêm tăng tận 2, 3 đơn vị. Hàm HAL_GPIO_EXTI_Callback() là hàm sẽ được gọi khi có ngắt ngoài xảy ra, chúng ta sẽ kiểm tra chân của của nó để biết nó thuộc ngắt ngoài dòng nào. Dòng if (++cnt > 9999) cnt = 0; có nhiệm vụ vừa tăng và kiểm tra xem biến đếm có vượt quá 999 không, nếu vượt quá biến đếm sẽ được lại về giá trị 0.Dòng while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)); có nhiệm vụ chờ cho đến khi nào nút USER được nhả ra thì mới tiếp tục.

    Như vậy chúng ta đã tìm hiểu xong về ngắt ngoài. Bài tiếp sẽ là giới thiệu về Timer, các bạn hãy chú ý đón đọc nhé!
     
    Last edited: 3/6/19

trang này