proton8489

Внешние прерывания STM32F10xxx

4 сообщения в этой теме

proton8489    2

Господа, имею следующий код (а он имеет меня), который вообще никак не заметен микроконтроллером (stm32f103rb, stm32f103c8). Подавая сигналы "0" или "1" на входы прерывания не выполняются. Пробовал вызывать внутреннее прерывание, но попытки были бессмысленны. Что здесь не так?


void NVIC_InputInit(void)
{ 
  RCC->APB2ENR |= RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPCEN; 	// Тактирование альтернативных функций и порта
  PIO_INIT_PIN(GPIOC,6,Input_Floating);     // PС6,7 на вход
  PIO_INIT_PIN(GPIOC,7,Input_Floating); 
  PIO_INIT_PIN(GPIOC,10,Output2_Push_Pull);  // PС10,11 на выход
  PIO_INIT_PIN(GPIOC,11,Output2_Push_Pull);
 
  AFIO->EXTICR[1] |= AFIO_EXTICR2_EXTI6_PC | AFIO_EXTICR2_EXTI7_PC;  // Настройка порта и выбор пинов для прерывания 
  EXTI->IMR |= EXTI_IMR_MR6 | EXTI_IMR_MR7;    // Разрешаем генерацию прерывания в периферии          
  EXTI->RTSR |= EXTI_RTSR_TR6 | EXTI_RTSR_TR7;  // Настроим прерывание на детектирование обоих фронтов            
  EXTI->FTSR |= EXTI_FTSR_TR6 | EXTI_FTSR_TR7;  // у двух входов   
  //EXTI->EMR |= EXTI_EMR_MR6; //Разрешение возобновления при внешних событиях

  // Разрешаем прерывания  
  //uint32_t prioritygroup = NVIC_GetPriorityGrouping();
  //uint32_t priority = NVIC_EncodePriority(prioritygroup, 1, 0 );
  //NVIC_SetPriority(EXTI9_5_IRQn, priority);
  NVIC_EnableIRQ(EXTI9_5_IRQn);  
  // Разрешаем глобальные прерывания  
  __enable_irq(); 

  //EXTI->SWIER |= EXTI_IMR_MR7; // Внутреннее прерывание
}

void EXTI9_5_IRQHandler(void) 
{
  if (EXTI->PR & (1<<6)) //проверяем прерывание от EXTI6
  { 
     EXTI->PR |= (1<<6);
    //EXTI->PR |= EXTI_PR_PR6; //сброс флага прерывания 
     
    PIO_RESET(GPIOC,11);   
  } 
  // if ((EXTI->PR & EXTI_PR_PR7) == EXTI_PR_PR7) 
  if (EXTI->PR & (1<<7)) //проверяем прерывание от EXTI6
  { 
    EXTI->PR |= (1<<7);
    //EXTI->PR |= EXTI_PR_PR7; //сброс флага прерывания 
    
    PIO_RESET(GPIOC,10); 
  }
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
proton8489    2

Ну неужели никто не знает и не подскажет? Проблема точно не аппаратная, контакт есть, а реакции на него нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
snn_krs    40

STM32F103C8, Keil 5 ниже код работает нормально. Проверьте в отладчике устанавливаются AFIO->EXTICR[1]. или нет.

 

void NVIC_InputInit(void)
{ 
  RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; 	// 
  AFIO->EXTICR[1] |= AFIO_EXTICR2_EXTI6_PB | AFIO_EXTICR2_EXTI7_PB;  //
  EXTI->IMR |= EXTI_IMR_MR6 | EXTI_IMR_MR7;    //
  EXTI->RTSR |= EXTI_RTSR_TR6 | EXTI_RTSR_TR7;  //
  EXTI->FTSR |= EXTI_FTSR_TR6 | EXTI_FTSR_TR7;  //
  NVIC_EnableIRQ(EXTI9_5_IRQn);  
  __enable_irq(); 
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
proton8489    2

У меня точно такой же код и в отладчике всё было с регистрами нормально, кроме захода в само прерывание. Но проблема решена. Оказывается надо было подключить к проекту файл стартапа (список векторов прерываний), который сам ни через что не цепляется.
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
UTSource

Найдите миллионы труднодоступных

электронных компонентов

Ваша публикация должна быть проверена модератором

Гость
Вы не авторизованы. Если у вас есть аккаунт, пожалуйста, войдите.
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Восстановить форматирование

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Загрузка...

  • Похожие публикации

    • Автор: LukaS_St
      Всем привет. Столкнулся с такой проблемой: Пишу программу для устройства мониторинга оборотов двух валов используя датчик холла. Настроил прерывания,  перевод в RPM, все проверил, в .порт отправляются верные значения, и после настройки индикации столкнулся с проблемой неадекватного поведения переменных считающих millis, а после и индикации. В Arduino я не спец, Гляньте на код, может чем помогите. Заранее благодарен.
      #include <EEPROM.h> #define CLOCK 13 //SH_CP #define DATA 11  //DS #define LATCH 10  //ST_CP int numbers[5]; boolean ee = 0; int mh; int hh; int et_mah; int et_shl; int ot_mah; int ot_shl; volatile  int rpm_mah = 0; volatile  int rpm_shl = 0;  int rpmmah_count = 0;  int rpmshl_count = 0; unsigned long lastmillis_mah = 0; unsigned long lastmillis_shl = 0; unsigned long lastmillis_show = 0; unsigned char number[] = {   0b01111110, //0   0b00110000, //1   0b01101101, //2   0b01111001, //3   0b00110011, //4   0b01011011, //5   0b01011111, //6   0b01110000, //7   0b01111111, //8   0b01111011, //9   0b00000001, //-   0b00000000  //тушим индикатор }; void setup() {   Serial.begin(9600);   attachInterrupt(0, rpm_mahovik, FALLING);   attachInterrupt(1, rpm_shluz, FALLING);   pinMode(CLOCK, OUTPUT);   pinMode(DATA, OUTPUT);   pinMode(LATCH, OUTPUT); } void rpm_mahovik() { /* this code will be executed every time the interrupt 0 (pin2) gets low.*/   rpmmah_count++; } void rpm_shluz() { /* this code will be executed every time the interrupt 0 (pin2) gets low.*/   rpmshl_count++; } // чтение //int EEPROM_int_read(int addr) { //  byte raw[2];  // for (byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr + i);  // int &num = (int&)raw; //  return num; //} // запись //void EEPROM_int_write(int addr, int num) { //  byte raw[2];  // (int&)raw = num;  // for (byte i = 0; i < 2; i++) EEPROM.write(addr + i, raw[i]); //} void show () {   int x;   for (x = 5; x >= 0; x--) {    Serial.print("x= "); Serial.println(x);     //включаем LATCH (Начинаем общение)     digitalWrite(LATCH, LOW);     shiftOut(DATA, CLOCK, LSBFIRST, number[numbers[x]]);     //выключаем LATCH     digitalWrite(LATCH, HIGH);     //отключаем LATCH (чтобы регистр не ждал данных)     digitalWrite(LATCH, HIGH);   } } //void ee_write () {  // EEPROM_int_write(0, mh); //  EEPROM_int_write(2, hh); //  EEPROM_int_write(4, et_mah); //  EEPROM_int_write(6, et_shl); //  EEPROM_int_write(8, ot_mah); //  EEPROM_int_write(10, ot_shl); //} void loop() { //  if ((millis() <= 100) & (ee == 0)) {   //  mh = EEPROM_int_read(0);  //   hh = EEPROM_int_read(2); //    et_mah = EEPROM_int_read(4);  //   et_shl = EEPROM_int_read(6);  //   ot_mah = EEPROM_int_read(8);  //   ot_shl = EEPROM_int_read(10);  //   ee = 1;  // }   if (millis() - lastmillis_mah == 1000) {     detachInterrupt(0);     rpm_mah = rpmmah_count * 60;     rpmmah_count = 0;     lastmillis_mah = millis();     attachInterrupt(0, rpm_mahovik, FALLING);   }   if (millis() - lastmillis_shl == 5000) {     detachInterrupt(1);     rpm_shl = rpmshl_count * 12;     rpmshl_count = 0;     lastmillis_shl = millis();     attachInterrupt(1, rpm_shluz, FALLING);   }   if (millis() - lastmillis_show == 1000) {     numbers[0] = rpm_mah / 1000;     numbers[1] = (rpm_mah % 1000) / 100;     numbers[2] = ((rpm_mah % 1000) % 100) / 10;     numbers[3] = ((rpm_mah % 1000) % 100) % 10;     numbers[4] = rpm_shl / 10;     numbers[5] = rpm_shl % 10;     lastmillis_show = millis();   show(); Serial.print("RPM mah= "); Serial.println (rpm_mah);  Serial.print("RPM shl= "); Serial.println (rpm_shl);   Serial.print("Show millis= "); Serial.println(lastmillis_show); Serial.print("Show mah= "); Serial.println(lastmillis_mah); Serial.print("Show shl= "); Serial.println(lastmillis_shl);   } }
    • Автор: Шампунь
      Добрый день. Пытаюсь сделать прерывания по изменению GP0. Ставлю GP0 на вход, разрешаю прерывания по изменению GPIO, разрешаю глобальные прерывания, ставлю бит IOC0 в 1. Но при изменении GP0 прерывание не срабатывает. Прерывание по переполнению таймера срабатывает отлично. Что я делаю не так? Прикладываю код программы. Если этого недостаточно, чтобы понять проблему, приложил полный код программы файлом.
      list p=12f683 #include "p12f683.inc" __config 0x3FF4 W_TEMP EQU 0x40 STATUS_TEMP EQU 0x41 flag EQU 0x42 org 0 goto start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org 0x04 MOVWF W_TEMP SWAPF STATUS,W MOVWF STATUS_TEMP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;программа обработки прерываний ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SWAPF STATUS_TEMP,W MOVWF STATUS SWAPF W_TEMP,F SWAPF W_TEMP,W retfie ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; start clrf GPIO movlw 0x07 movwf CMCON0 bsf STATUS,RP0 ;1 bank movlw b'00001001' movwf TRISIO movlw b'10000001' movwf OPTION_REG bcf INTCON,T0IF bsf INTCON,T0IE movf GPIO,w bcf INTCON,GPIF bsf INTCON,GPIE bsf INTCON,GIE movlw b'00000001' movwf IOC bcf STATUS,RP0 ;0 bank movlw .0 movwf TMR0 ask btfss flag,4 ;данный бит устанавливается в программе обработки прерываний goto ask bcf flag,4 call indicate ;подпрограмма indicate выводит значение, полученное в результате ;обработки прерывания, на индикаторы goto ask  
      reciever1.asm
    • Автор: vintik87
      Добавил Модбас в проект все работало.  Добавил еще несколько функций в main и модбас перестал работать. Когда присоединяю сериальный кабель модбас IAR дебагер пререстает работать (вероятно есть общие линии).  Вопросы :  1. как решить конфликт кабелей (IAR JTAG) и Modbus  и отлаживать модбас с его кабелем  ?  2. Если решить конфликт кабелей нельзя тогда ... Как симулировать прерывания на ногах UART (модбас) чтобы программа зашла в обработчит прерывания модбас ?
    • Автор: Тимур1992
      Доброго времени суток.
      Решил пробудить свои скилы по написанию программ под stm32f103. Поигрался с SMT32CUDEMX и HAL, но вернулся к SLP библиотеке.  Начал постепенно наращивать программу по примерам, начиная с GPIO, тактирования и на работе c USART встал. Суть в том что передача по UART идет нормально, а вот прием приводит к "зависанию". Устанавливая бесконечные while с мигалками внутри, я выяснил что по все видимости МК не переходит в прерывания USART1_IRQHandler. Я не могу понять в чем ошибка, раньше с таким не сталкивался, хотя написал несколько программ для stm32f100 .____.
      Среда разработки Atollic TrusStudio 9.0.0.
       
      #include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" #include "stm32f10x_usart.h" #include "misc.h" #include <string.h> // тактовый светодиод для индикации #define LED GPIO_Pin_5 #define RX_BUF_SIZE 80 volatile char RX_FLAG_END_LINE = 0; volatile char RXi; volatile char RXc; volatile char RX_BUF[RX_BUF_SIZE] = {'\0'}; volatile char buffer[80] = {'\0'}; void init_GPIO(void); void SetSysClockTo72(void); void init_uart(void); void clear_RXBuffer(void); void USARTSend(const char *pucBuffer); void USART1_IRQHandler(void) { GPIO_ResetBits(GPIOA, LED); //GPIOA->ODR ^= LED; //USART_ITConfig(USART1, USART_IT_RXNE, DISABLE); //if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { //if ((USART1->SR & USART_FLAG_RXNE) != RESET) { //if ((USART1->SR & USART_SR_RXNE) != (u16)RESET) { if (USART1->SR & USART_SR_RXNE) { // Сбрасываем флаг прерывания USART1->SR &=~ USART_SR_RXNE; //RXc = USART_ReceiveData(USART1); //RX_BUF[RXi] = RXc; //RXi++; //if (RXc != 13) { // if (RXi > RX_BUF_SIZE-1) { // clear_RXBuffer(); // } //} //else { // RX_FLAG_END_LINE = 1; //} //Echo //USARTSend("Interrapt_UART1\r\n"); //USART_SendData(USART1, RXc); } //return } int main(void) { int i; //SetSysClockTo72(); init_GPIO(); init_uart(); USARTSend("Test USART1\r\n"); while (1) { //if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9) != 0) { /* Toggle LED which connected to PC13*/ GPIOA->ODR ^= LED; // Invert C13 /* delay */ for(i=0;i<0x100000;i++); /* Toggle LED which connected to PC13*/ GPIOA->ODR ^= LED; /* delay */ for(i=0;i<0x100000;i++); USARTSend("Test USART1\r\n"); //} //else { //GPIO_SetBits(GPIOA, LED); //} } } void init_GPIO(void) { // Создаем класс для постепенной настройки параметров и единовременного применени¤ GPIO_InitTypeDef GPIO_InitStructure; //Настрайваем светодиод, включаем тактирование GPIOA RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // Конфигурация для светодиода, режим работы, максимальная скорость GPIO_InitStructure.GPIO_Pin = LED; // GPIO_Mode_Out_OD выход с открытым стоком, GPIO_Mode_Out_PP выход двумя состояниями // GPIO_Mode_AF_OD выход с открытым стоком для альтернативных функций, GPIO_Mode_AF_PP то же самое, но с двумя состояниями GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // Устанавливаем начальное значение SetBits -> High level ("1"), ResetBits -> Low level ("0") GPIO_ResetBits(GPIOA, LED); // Настрайваем пин 9, регистра B на вход, для отладки, включаем тактирование регистра B RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // Настрайваем для кнопку, пин, режим, максимальная частота входного сигнала GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // GPIO_Mode_AIN аналоговый вход, GPIO_Mode_IN_FLOATING вход без подтяжки, болтающийся // GPIO_Mode_IPD вход с подтяжкой к земле, GPIO_Mode_IPU вход с подтяжкой к питанию GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } void SetSysClockTo72(void) { ErrorStatus HSEStartUpStatus; /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------------------------*/ /* Системный RESET RCC (делать не обязательно, но полезно на этапе отладки) */ RCC_DeInit(); /* Включаем HSE (внешний кварц) */ RCC_HSEConfig( RCC_HSE_ON); /* Ждем пока HSE будет готов */ HSEStartUpStatus = RCC_WaitForHSEStartUp(); /* Если с HSE все в порядке */ if (HSEStartUpStatus == SUCCESS) { /* HCLK = SYSCLK */ /* Смотри на схеме AHB Prescaler. Частота не делится (RCC_SYSCLK_Div1) */ RCC_HCLKConfig( RCC_SYSCLK_Div1); /* PCLK2 = HCLK */ /* Смотри на схеме APB2 Prescaler. Частота не делится (RCC_HCLK_Div1) */ RCC_PCLK2Config( RCC_HCLK_Div1); /* PCLK1 = HCLK/2 */ /* Смотри на схеме APB1 Prescaler. Частота делится на 2 (RCC_HCLK_Div2) потому что на выходе APB1 должно быть не более 36МГц (смотри схему) */ RCC_PCLK1Config( RCC_HCLK_Div2); /* PLLCLK = 8MHz * 9 = 72 MHz */ /* Указываем PLL от куда брать частоту (RCC_PLLSource_HSE_Div1) и на сколько ее умножать (RCC_PLLMul_9) */ /* PLL может брать частоту с кварца как есть (RCC_PLLSource_HSE_Div1) или поделенную на 2 (RCC_PLLSource_HSE_Div2). Смотри схему */ //RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); RCC_PLLConfig(0x00010000, RCC_PLLMul_9); /* Включаем PLL */ RCC_PLLCmd( ENABLE); /* Ждем пока PLL будет готов */ while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) { } /* Переключаем системное тактирование на PLL */ RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK); /* Ждем пока переключиться */ while (RCC_GetSYSCLKSource() != 0x08) { } } else { /* Проблемы с HSE. Тут можно написать свой код, если надо что-то делать когда микроконтроллер не смог перейти на работу с внешним кварцом */ /* Пока тут заглушка - вечный цикл*/ // while (1) { //} } } void init_uart(void) { /* Enable USART1 and GPIOA clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE); /* Configure the GPIOs */ GPIO_InitTypeDef GPIO_InitStructure; /* Configure USART1 Tx (PA.09) as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART1 Rx (PA.10) as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure the USART1 */ USART_InitTypeDef USART_InitStructure; /* USART1 configuration ------------------------------------------------------*/ /* USART1 configured as follow: - BaudRate = 115200 baud - Word Length = 8 Bits - One Stop Bit - No parity - Hardware flow control disabled (RTS and CTS signals) - Receive and transmit enabled - USART Clock disabled - USART CPOL: Clock is active low - USART CPHA: Data is captured on the middle - USART LastBit: The clock pulse of the last data bit is not output to the SCLK pin */ USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); /* Enable USART1 */ USART_Cmd(USART1, ENABLE); /* Enable the USART1 Receive interrupt: this interrupt is generated when the USART1 receive data register is not empty */ USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* NVIC Configuration */ NVIC_InitTypeDef NVIC_InitStructure; /* Enable the USARTx Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //NVIC_EnableIRQ(USART1_IRQn); } void clear_RXBuffer(void) { for (RXi=0; RXi<RX_BUF_SIZE; RXi++) RX_BUF[RXi] = '\0'; RXi = 0; } void USARTSend(const char *pucBuffer) { while (*pucBuffer) { USART_SendData(USART1, *pucBuffer++); while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) { } } }  
    • Автор: melkiy93
      Доброго!
      Контроллер stm32f103c8t6. Пишу настройку таймера и его прерываний, но программа зависает через несколько тиков после выхода из самой функции настройки.
      По коду: в главной функции пишу сразу настройку таймера и далее бесконечный цикл, до которого дело не доходит.
      На рисунках скрины отладки в момент зависания.
      void TIM_ini(void) { TIM_TimeBaseInitTypeDef UserTimStruct; NVIC_InitTypeDef UserNVIC_Structure; TIM_DeInit(TIM3); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); UserTimStruct.TIM_ClockDivision = TIM_CKD_DIV4; UserTimStruct.TIM_CounterMode = TIM_CounterMode_Up; UserTimStruct.TIM_Period = 200; UserTimStruct.TIM_Prescaler = 700-1; TIM_TimeBaseInit(TIM3, &UserTimStruct); TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); TIM_Cmd(TIM3, ENABLE); UserNVIC_Structure.NVIC_IRQChannel = TIM3_IRQn; UserNVIC_Structure.NVIC_IRQChannelCmd = ENABLE; UserNVIC_Structure.NVIC_IRQChannelPreemptionPriority = 1; UserNVIC_Structure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&UserNVIC_Structure); } ,