У меня есть нуклео плата, и на ней есть кнопка. Кнопка подключена к контакту C13, и при нажатии на нее я должен остановить распространение ШИМ-сигнала. Может кто-то указать мне верное направление?
Вот код для определения прерывания и его поведения.
void INTERRUPT_CONFIG(){
RCC->APB2ENR|=RCC_APB2ENR_SYSCFGEN;
SYSCFG->EXTICR[2]|=(0x2<<SYSCFG_EXTICR1_EXTI1_Pos);
EXTI->IMR|=(0x1<<EXTI_IMR_MR1_Pos);
EXTI->RTSR|=(0x1<<EXTI_RTSR_TR13_Pos);
EXTI->FTSR|=(0x0<<EXTI_FTSR_TR13_Pos);
NVIC_SetPriority(EXTI1_IRQn,1);
NVIC_EnableIRQ(EXTI1_IRQn);
}
bool flag=false;
void EXTI1_IRQHandler(){
if (EXTI->PR & EXTI_PR_PR13_Pos){
EXTI->PR|=(0x0<<EXTI_PR_PR13_Pos);
flag=!flag;
}
}
... и вот основная функция:
int main(void)
{
TIM2_INIT();
//button is pc13
INTERRUPT_CONFIG();
EXTI1_IRQHandler();
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
GPIOC->MODER |= ( 0x0 << GPIO_MODER_MODE13_Pos);
GPIOC->PUPDR |= ( 0x1 << GPIO_PUPDR_PUPD13_Pos);//defining the Pin c13
while (1)
{
if (flag==true){
TIM2->CR1&=~(TIM_CR1_CEN);
}
else{
int x;
for(x=0; x<500; x=x+1)
{
TIM2->CCR1=x;
delayFunct(1);
}
for(x=500; x>0; x=x-1)
{
TIM2->CCR1=x;
delayFunct(1);
}
}
Я знаю, что вопрос немного многословен, но все равно буду признателен за помощь. Ребята, заранее спасибо.
До сих пор я возился с содержимым значений регистра EXTI, но безрезультатно.
нет volatile не помогает
1) if (EXTI->PR & EXTI_PR_PR13_Pos) неверно, битовая маска для вывода 13 должна быть 0x01 << EXTI_PR_PR13_Pos. 2) почему ты звонишь EXTI1_IRQHandler(); в main()? 3) не знаю, какова логика вашего дизайна, вам либо вообще не нужен flag (останавливает таймер навсегда), либо вы забыли сбросить flag в main(), и 4) в последнем случае flag необходимо объявить как volatile.
Спасибо @hcheung и всем остальным, я внесу изменения сегодня и посмотрю, как они проверятся, и буду держать вас в курсе.
Еще одна вещь, я думаю, что в регистр EXT1->PR обычно записывают 1, чтобы очистить флаг прерывания, так и должно быть EXTI->PR |= (1<<EXTI_PR_PR13_Pos);, вам следует проверить Справочное руководство, чтобы подтвердить это.
@hcheung Я исправил прерывание кнопки, добавив NVIC_SetVector(EXTI15_10_IRQn, EXTI15_10_IRQn);, и это заработало, но теперь моя кнопка срабатывает только 1 раз, то есть я не могу остановить и запустить ШИМ, только остановить его, пытаясь найти решение этой проблемы сейчас
Именно об этом я и говорил в пункте 3 в своем комментарии. Вы устанавливаете flag в прерывании, но нет возможности сбросить flag, и если вы посмотрите на логику кода, он навсегда отключает таймер, когда установлен флаг.





В качестве предисловия скажу, что некоторые вещи были довольно сильно изменены по совету моего наставника, например, логика в IRQ, использование объединений, надеюсь, вы все еще могу понять код
void Interrupt_Init(void){
EXTI15_10_Init();
NVIC->IP[EXTI15_10_IRQn] = (1 << 4);
NVIC->ISER[40 >> 5] |= (1 << (40 % 32));
}
union InterruptFlag {
struct {
volatile bool flag: 1; // Just one bit for our flag
volatile bool press: 1;
} bits_access;
uint32_t reg; // We'll use this for byte access
};
volatile union InterruptFlag flag = { .bits_access.flag = 0 }; //
Initialize
to 0
volatile uint16_t pressTime;
volatile bool lastButtonPress=0;
volatile bool buttonPress=1;
void EXTI15_10_IRQHandler(void){
flag.bits_access.flag = !flag.bits_access.flag;
EXTI->PR |= (1<<13); // Clear PR to re-enable EXTI interrupt
}
void clearIR(void){
flag.bits_access.flag = 0;
buttonPress=0;
}
и теперь что касается нового содержимого основной функции, определение функций такое же, изменился только цикл while; пока (1) {
int x;
for(x=0; x<500; x++)
{
if (flag.bits_access.flag== 1){
x=x-1;
TIM2->CCR1=x;
}
else{
TIM2->CCR1=x;
delayTRIP(1);
}}
for(x=500; x>0; x--)
{
if (flag.bits_access.flag== 1){
x=x+1;
TIM2->CCR1=x;
}
else{
TIM2->CCR1=x;
delayTRIP(1);
}
}
}}
Разделите вопросы: обнаружение кнопки и остановка ШИМ. Кстати, обычно это плохая идея использовать (крайние) прерывания с кнопками в качестве отскока кнопки. -- О, а какой конкретно у вас вопрос?