Hiển thị các bài đăng có nhãn stm32. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn stm32. Hiển thị tất cả bài đăng

Thứ Năm, 2 tháng 4, 2020

DAC with STM32 | Study STM32 with Standard Peripheral Library

Fitted sine wave (dotted line) and residuals in an ideal quantizer ...


@par Example Description 

This example provides a short description of how to use the DAC peripheral to
generate several signals using DMA controller.
When the user presses the KEY push-button, DMA transfers the two selected
waveforms to the DAC.
For each press on KEY button, 2 signals has been selected and can be monitored on 
the two DAC channels:
    - Escalator waveform (Channel 1) and Sine waveForm (Channel 2).
    - Noise waveform (Channel 1) and Triangle waveform (Channel 2).


@par Directory contents 

  - DAC/DAC_SignalsGeneration/stm32f4xx_conf.h    Library Configuration file
  - DAC/DAC_SignalsGeneration/stm32f4xx_it.c      Interrupt handlers
  - DAC/DAC_SignalsGeneration/stm32f4xx_it.h      Interrupt handlers header file
  - DAC/DAC_SignalsGeneration/main.c              Main program
  - DAC/DAC_SignalsGeneration/main.h              Main program header file
  - DAC/DAC_SignalsGeneration/system_stm32f4xx.c  STM32F4xx system source file


1. main.c
/* Includes ------------------------------------------------------------------*/
#include "main.h"


DAC_InitTypeDef  DAC_InitStructure;

const uint16_t aSine12bit[32] = {
                      2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4095, 4056,
                      3939, 3750, 3495, 3185, 2831, 2447, 2047, 1647, 1263, 909,
                      599, 344, 155, 38, 0, 38, 155, 344, 599, 909, 1263, 1647};
const uint8_t aEscalator8bit[6] = {0x0, 0x33, 0x66, 0x99, 0xCC, 0xFF};

__IO uint8_t ubSelectedWavesForm = 1;
__IO uint8_t ubKeyPressed = SET;

/* Private function prototypes -----------------------------------------------*/
static void TIM6_Config(void);

static void DAC_Ch1_EscalatorConfig(void);
static void DAC_Ch2_SineWaveConfig(void);

static void DAC_Ch1_NoiseConfig(void);
static void DAC_Ch2_TriangleConfig(void);


int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       files (startup_stm32f40xx.s/startup_stm32f427x.s) before to branch to
       application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f4xx.c file
     */   

  /* Preconfiguration before using DAC----------------------------------------*/
  GPIO_InitTypeDef GPIO_InitStructure;

  /* DMA1 clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
  /* GPIOA clock enable (to be used with DAC) */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);                       
  /* DAC Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

  /* DAC channel 1 & 2 (DAC_OUT1 = PA.4)(DAC_OUT2 = PA.5) configuration */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* TIM6 Configuration ------------------------------------------------------*/
  TIM6_Config(); 
 
  /* Configures Key Button */
  STM_EVAL_PBInit(BUTTON_KEY, BUTTON_MODE_EXTI);
 
  while (1)
  {
    /* If the Key is pressed */
    if (ubKeyPressed != RESET)
    {           
      DAC_DeInit();

      /* select waves forms according to the Key Button status */
      if (ubSelectedWavesForm == 1)
      {
        /* The sine wave and the escalator wave has been selected */

        /* Escalator Wave generator ------------------------------------------*/
        DAC_Ch1_EscalatorConfig();

        /* Sine Wave generator -----------------------------------------------*/
        DAC_Ch2_SineWaveConfig();
       
      }
      else
      {
        /* The triangle wave and the noise wave has been selected */

        /* Noise Wave generator ----------------------------------------------*/
        DAC_Ch1_NoiseConfig();

        /* Triangle Wave generator -------------------------------------------*/
        DAC_Ch2_TriangleConfig();
      }
     
      ubKeyPressed = RESET;
    }
  }
}

/**           
  * @brief  TIM6 Configuration
  * @note   TIM6 configuration is based on APB1 frequency
  * @note   TIM6 Update event occurs each TIM6CLK/256 
  * @param  None
  * @retval None
  */
static void TIM6_Config(void)
{
  TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
  /* TIM6 Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
 
  /* --------------------------------------------------------
  TIM3 input clock (TIM6CLK) is set to 2 * APB1 clock (PCLK1),
  since APB1 prescaler is different from 1. 
    TIM6CLK = 2 * PCLK1 
    TIM6CLK = HCLK / 2 = SystemCoreClock /2
         
  TIM6 Update event occurs each TIM6CLK/256

  Note:
   SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f4xx.c file.
   Each time the core clock (HCLK) changes, user had to call SystemCoreClockUpdate()
   function to update SystemCoreClock variable value. Otherwise, any configuration
   based on this variable will be incorrect.   

  ----------------------------------------------------------- */
  /* Time base configuration */
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_Period = 0xFF;         
  TIM_TimeBaseStructure.TIM_Prescaler = 0;     
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;   
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
  TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);

  /* TIM6 TRGO selection */
  TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
 
  /* TIM6 enable counter */
  TIM_Cmd(TIM6, ENABLE);
}

/**
  * @brief  DAC  Channel2 SineWave Configuration
  * @param  None
  * @retval None
  */
static void DAC_Ch2_SineWaveConfig(void)
{
  DMA_InitTypeDef DMA_InitStructure;
 
  /* DAC channel2 Configuration */
  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
  DAC_Init(DAC_Channel_2, &DAC_InitStructure);

  /* DMA1_Stream6 channel7 configuration **************************************/
  DMA_DeInit(DMA1_Stream6);
  DMA_InitStructure.DMA_Channel = DMA_Channel_7; 
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R2_ADDRESS;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&aSine12bit;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_BufferSize = 32;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;       
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA1_Stream6, &DMA_InitStructure);

  /* Enable DMA1_Stream6 */
  DMA_Cmd(DMA1_Stream6, ENABLE);

  /* Enable DAC Channel2 */
  DAC_Cmd(DAC_Channel_2, ENABLE);

  /* Enable DMA for DAC Channel2 */
  DAC_DMACmd(DAC_Channel_2, ENABLE);
}

/**
  * @brief  DAC Channel1 Escalator Configuration
  * @param  None
  * @retval None
  */
static void DAC_Ch1_EscalatorConfig(void)
{
  DMA_InitTypeDef DMA_InitStructure;

  /* DAC channel1 Configuration */
  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
  DAC_Init(DAC_Channel_1, &DAC_InitStructure);

  /* DMA1_Stream5 channel7 configuration **************************************/ 
  DMA_DeInit(DMA1_Stream5);
  DMA_InitStructure.DMA_Channel = DMA_Channel_7; 
  DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR8R1_ADDRESS;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&aEscalator8bit;
  DMA_InitStructure.DMA_BufferSize = 6;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;       
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA1_Stream5, &DMA_InitStructure);   

  /* Enable DMA1_Stream5 */
  DMA_Cmd(DMA1_Stream5, ENABLE);
 
  /* Enable DAC Channel1 */
  DAC_Cmd(DAC_Channel_1, ENABLE);

  /* Enable DMA for DAC Channel1 */
  DAC_DMACmd(DAC_Channel_1, ENABLE);
}

/**
  * @brief  DAC Channel2 Triangle Configuration
  * @param  None
  * @retval None
  */
static void DAC_Ch2_TriangleConfig(void)
{
 /* DAC channel2 Configuration */
  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;
  DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_1023;
  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
  DAC_Init(DAC_Channel_2, &DAC_InitStructure);

  /* Enable DAC Channel2 */
  DAC_Cmd(DAC_Channel_2, ENABLE);

  /* Set DAC channel2 DHR12RD register */
  DAC_SetChannel2Data(DAC_Align_12b_R, 0x100);
}

/**
  * @brief  DAC  Channel1 Noise Configuration
  * @param  None
  * @retval None
  */
static void DAC_Ch1_NoiseConfig(void)
{
 /* DAC channel1 Configuration */
  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Noise;
  DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bits10_0;
  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
  DAC_Init(DAC_Channel_1, &DAC_InitStructure);

  /* Enable DAC Channel1 */
  DAC_Cmd(DAC_Channel_1, ENABLE);

  /* Set DAC Channel1 DHR12L register */
  DAC_SetChannel1Data(DAC_Align_12b_L, 0x7FF0);
}

#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 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) */

  /* Infinite loop */
  while (1)
  {
  }
}

#endif

Chủ Nhật, 31 tháng 3, 2019

[ Học ARM-Bài3 ] ADC STM32 với Standard Peripheral Library

Author: Cong Neb
Alias: Dark Neb
Studied at: SET BKHN K57
Nếu copy tài liệu: Nhớ ghi nguồn tác giả..Tk


Registers:

__IO uint32_t SR
__IO uint32_t CR1
__IO uint32_t CR2
__IO uint32_t SMPR1
__IO uint32_t SMPR2
__IO uint32_t JOFR1
__IO uint32_t JOFR2
__IO uint32_t JOFR3
__IO uint32_t JOFR4
__IO uint32_t HTR
__IO uint32_t LTR
__IO uint32_t SQR1
__IO uint32_t SQR2
__IO uint32_t SQR3
__IO uint32_t JSQR
__IO uint32_t JDR1
__IO uint32_t JDR2
__IO uint32_t JDR3
__IO uint32_t JDR4

__IO uint32_t DR


Các bước khởi tạo ADC

1.  Enable the ADC interface clock using

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADCx, ENABLE);
2.  ADC pins configuration
3.  Configure the ADC Prescaler, conversion resolution and data alignment using  the ADC_Init() function.

4.  Activate the ADC peripheral using ADC_Cmd() function.

Các function chính

1.ADC_DeInit
void ADC_DeInit ( void )

Thứ Sáu, 15 tháng 3, 2019

[Học ARM-Bài0] RCC STM32 với Standard Peripheral Library

Author: Cong Neb
Alias: Dark Neb
Studied at: SET BKHN K57
Nếu copy tài liệu: Nhớ ghi nguồn tác giả..Tks

Reset and clock control (RCC)
RCC là một khối cực kì quan trọng của MCU... Nếu không có RCC MCU của ta sẽ không khác gì các con IC như 555..ect chứ không còn là MCU nữa...
MCU chỉ làm việc được khi được cung cấp 1 xung Clock... Và RCC làm việc đó...
Nếu nói Nguồn là năng lượng thì RCC là hơi thở của MCU...

Chức năng: Cung cấp xung Clock cho hệ thống...
RCC_TypeDef is defined in the stm32f2xx.h file and contains the RCC registers

Các Registers:

__IO uint32_t CR
__IO uint32_t PLLCFGR
__IO uint32_t CFGR
__IO uint32_t CIR
__IO uint32_t AHB1RSTR
__IO uint32_t AHB2RSTR
__IO uint32_t AHB3RSTR
uint32_t RESERVED0
__IO uint32_t APB1RSTR
__IO uint32_t APB2RSTR
uint32_t RESERVED1
__IO uint32_t AHB1ENR
__IO uint32_t AHB2ENR
__IO uint32_t AHB3ENR
uint32_t RESERVED2
__IO uint32_t APB1ENR
__IO uint32_t APB2ENR
uint32_t RESERVED3
__IO uint32_t AHB1LPENR
__IO uint32_t AHB2LPENR
__IO uint32_t AHB3LPENR
uint32_t RESERVED4
__IO uint32_t APB1LPENR
__IO uint32_t APB2LPENR
uint32_t RESERVED5
__IO uint32_t BDCR
__IO uint32_t CSR
uint32_t RESERVED6
__IO uint32_t SSCGR
__IO uint32_t PLLI2SCFGR

// Mình khác Shock khi lần đầu đọc về các Reg của RCC...Nhiều vch.
Nhưng nó là khối rất quan trọng của MCU nên ta phải tìm hiểu nó...

Thứ Tư, 9 tháng 1, 2019

[Học ARM] Lập trình GPIO In/Out của vi điều khiển – STM32

General-purpose Input/Output (GPIO) rất phổ biến, là một chức năng ngoại vi cơ bản của mỗi loại vi điều khiển, bao gồm các chân đầu vào và chân đầu ra, có thể được điều khiển bởi người dùng. Nó tương tự với các dòng vi điều khiển 8bit như AVR hoặc PIC. Không giống như những dòng vi điều khiển 8bit, chỉ có 8 chân IO trên 1 port thì ở các vi điều khiển 32bit, có đến 16 chân IO trên 1 port. Cụ thể đối với chip STM32F103C8Tx gồm có 3 Port chính đó là GPIOA, GPIOB, GPIOC. Không phải tất cả các port đều có 16 chân, chỉ riêng GPIOA, GPIOB trên kit thì có đủ 16 chân GPIO.

Tiếp theo chúng ta đến phần cấu trúc 1 chân GPIO của chip:



Có 2 khối điều khiển khác nhau (khung hình nét đứt) như ở hình trên

– Output

– Input và các điều khiển đầu ra khác

Chức năng của GPIO bao gồm:




Bài viết này sẽ hướng dẫn về chức năng Output states: Output push-pull. Sau đây sẽ là sơ lược về cấu trúc phần cứng và khối điều khiển Output.


1. Các thanh ghi dữ liệu:

Bit set/reset register:

Ở mỗi chân general-purpose I/O port đều có 2 thanh ghi cấu hình 32 bit (GPIOx_CRL, GPIO_CRH: Control Register High, Control Register Low):

– Thanh ghi 32 bit dùng để set/reset các bit ở các chân IO (GPIOx_BSRR: Bit Set Reset Register)

– Thanh ghi 16 bit reset các bit ở các chân IO (GPIOx_BRR: Bit Reset Register) với x là các port của vi điều khiển.

Output data register:

Dữ liệu sau khi các bit đã được set/reset ở thanh ghi trên sẽ được truyền sang thanh ghi dữ liệu đầu ra 32bit (GPIOx_ODR: Output data register) và truyền đến khối điều khiển để xuất mức tín hiệu cho chân IO. Ngoài ra đối với thanh ghi này, chúng ta có thể đọc dữ liệu để xem trạng thái hiện tại của các chân IO đang ở mức “1” hoặc mức “0”.

2.Cách xuất mức tín hiệu output thông qua khối CMOS:

Ở push-pull mode:

Cấu hình chân I/O là ngõ ra, khi output control = 0 thì P-MOS sẽ dẫn, chân I/O sẽ nối VDD, còn khi output control = 1 thì N-MOS dẫn, chân I/O được nối VSS.

Khi ghi các bit Reset vào thanh ghi GPIOx_BSRR hoặc GPIOx_BRR dữ liệu sẽ được truyền sang thanh ghi output và đẩy tới khối điều khiển. Đầu ra của P-MOS sẽ là mức 1 vì ở trước P-MOS có 1 cổng đảo tín hiệu và N-MOS sẽ là mức 0, thì lúc này P-MOS sẽ được kích và chân IO có tín hiệu mức “1”:



Ngược lại, khi ghi các bit Set vào thanh ghi GPIOx_BSRR dữ liệu sẽ được truyền sang thanh ghi output và đẩy tới khối điều khiển. Đầu ra của P-MOS sẽ là mức 0 vì ở trước P-MOS có 1 cổng đảo tín hiệu và N-MOS sẽ là mức 1, thì lúc này N-MOS sẽ được kích và chân IO có tín hiệu mức “0”:



Chúng ta sẽ sử dụng CubeMX để sinh code và lập trình trên môi trường KeilC-V5. Khi sinh code, chúng ta sẽ làm việc dựa trên lớp thư viện HAL-Hardware Abstraction Layerr. Thư viện này được xây dựng dựa trên các thư viện tiêu chuẩn (Std) của STM32, để tiếp cận được nhanh chóng dòng vi điều khiển này thì chúng ta sẽ không đi quá sâu vào việc set/reset các bit ở trong thanh ghi. Mà sử dụng phần mềm CubeMX để sinh code và sử dụng các hàm GPIO có sẵn trong thư viện HAL.

Thứ Sáu, 3 tháng 11, 2017

Hướng dẫn sửa chữa chip do cấu hình Debug sai (cho STM32)

Hướng dẫn sửa chữa chip do cấu hình Debug sai (cho STM32)

Nếu như bạn không thể nạp được chip lần nữa sau lần nạp đầu tiên thì tức là bạn đã không cấu hình Debug (hoặc cấu hình sai). Khi đó chip sẽ mặc định chân PA13 và PA14 không phải là chân nạp chip theo chuẩn SWD nữa nên mọi hoạt động cố gắng nạp cho chip lúc này trở nên vô ích.

Rất may vẫn có cách để khắc phục sự cố này, bạn có thể làm theo các bước sau:
B1: Tạo lại chương trình của bạn bằng STM32CubeMX và lần này cấu hình đúng như trong hướng dẫn nạp chip.
B2: Sau khi tạo lại code trên trình biên dịch (Keilv5 hoặc IAR for STM32) bạn biên dịch chương trình đó.
B3: Trước khi cắm lại mạch nạp, bạn phải cắm jump nối vào BOOT0 và BOOT1. Sau đó bạn cắm mạch nạp vào máy tính.

Trong trường hợp bạn dùng kit khác bạn phải đảm bảo chân BOOT0 phải được cấp mức 1 vào BOOT1 (PB2) phải cấp mức 0 như bảng dưới đây (có thể tham khảo chi tiết hơn trong “Reference Manual” của chip )


Image result for boot configuration stm32

B4: Lúc này chip sẽ chạy ở trong vùng nhớ System của chip.
Do chip đã truy cập vào vùng nhớ System nên không có khả năng truy cập vào vùng nhớ Flash (chứa chương trình của bạn) nữa nên bạn hoàn toàn có thể nạp lại chương trình của bạn trong chế độ này.
B5: Sau khi bạn nạp xong chương trình với cấu hình đúng, bạn phải rút mạch nạp ra và gỡ jump nối ở BOOT0 và BOOT1 để chip có thể truy cập lại vào vùng nhớ Flash.
B6: Cắm lại mạch nạp và bạn có thể thấy chương trình của bạn lúc này đã hoạt động và bạn có thể nạp lại chương trình.

Chúc các bạn thành công.



Thứ Ba, 31 tháng 10, 2017

Ngắt trong STM32 là gì?


Image result for stm32

Ngắt trong vi điều khiển STM32 là gì?
Interrupt là gì?

Xin chào các bạn,sau đây mình xin giới thiệu chức năng ngắt trong STM32
Giống như Timer,Ngắt là một module rất quan trọng của STM32,sử dụng ngắt giúp chúng ta không phải mất thời gian kiểm tra liên tục đoạn chương trình nào đó,ngoài ra chúng ta có thể sử dụng ngắt để đồng thời cho STM32 cùng 1 lúc làm"nhiều nhiệm vụ" .

Khi điều kiện ngắt xảy ra,vi điều khiển sẽ tạm dừng chương trình đang thực hiện để nhảy tới chương trình ngắt,sau khi thực hiện xong chương trình ngắt,STM32 tiếp tục thực hiện các chương trình trước đó đang làm.

Chú ý:Chương trình ngắt không có đối số truyền vào và cũng không được gọi trực tiếp từ hàm main() hay một chương trình con khác.

Để hiểu rõ hơn về Ngắt(Interrupt) chúng ta cùng xem ví dụ sau:

void main() {
while(1) {
LED1=1;
delay_ms(1000);
LED1=0;
delay_ms(1000);

if(button)
LED2=1;
else
LED2=0;
}
}

Chúng ta có thể thấy: LED1 sẽ luôn nhấp nháy mỗi 1s.
Khi ta bấm nút (button) thì LED2 đôi khi sẽ không sáng.Nguyên nhân là sao? Do trong ngôn ngữ C/C++ các hàm đều thực hiện theo nguyên tắc tuần tự (Từ trên xuống dưới):
Giả sử hàm main () đang thực hiện lệnh:
LED1=1;
delay_ms(1000);
Lúc này,dù ta có bấm nút thì LED2 cũng sẽ không sáng do chương trình đang trong hàm delay_ms().

Để khắc phục,ta phải sử dụng Ngắt(Interrupt).
Ở bài sau mình sẽ hướng dẫn các bạn cách sử dụng Ngắt trong STM32.

XIn cảm ơn,hẹn gặp lại.