Миландр

Ключевым подразделением нашей компании является Центр Проектирования интегральных микросхем
Текущее время: 2019-фев-21 03:09

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 39 ]  На страницу 1, 2, 3  След.
Автор Сообщение
СообщениеДобавлено: 2019-янв-17 21:33 
Не в сети

Зарегистрирован: 2019-янв-17 21:29
Сообщения: 21
Здравствуйте, не раз уже здесь об этом говорили, но всё равно никак не могу разобраться. Работаю с К1986ВЕ92QI MILESTONE. Пытаюсь реализовать внешнее прерывание по кнопке PB10, чтобы переключаться между светодиодами. Подскажите, что делаю не так и как это исправить.
Код:
#include "main.h"
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include "MDR32Fx.h"
#include "system_MDR32F9Qx.h"
#include "MDR32F9Qx_config.h"

//PB8 - Green, PB9 - Red, PB10 - Button
int flag = 0;
void EXT_INT2_IRQHandler(void)
{
    flag = 1;
}
int main(void)
{
    int count = 1;
    //Настройка порта B - зелёный диод, красный диод, кнопка
    MDR_RST_CLK -> PER_CLOCK |= (1 << 22);
    MDR_PORTB -> OE |= (1 << 8) | (1 << 9) | (0 << 10);
    MDR_PORTB -> FUNC |= (3 << 8*2) | (0 << 9*2) | (2 << 10*2);
    MDR_PORTB -> ANALOG |= (1 << 8) | (1 << 9) | (1 << 10);
    MDR_PORTB -> PULL |= ((1 << 8) | (1 << 9) | (1 << 10)) << 16;
    MDR_PORTB -> PD |= (0 << 8) | (0 << 9) | (1 << 10) << 16;
    MDR_PORTB -> PWR |= (1 << 8*2) | (1 << 9*2) | (1 << 10*2);
    MDR_PORTB -> GFEN |= (0 << 8) | (0 << 9) | (1 << 10);
    __enable_irq;
    NVIC_EnableIRQ(EXT_INT2_IRQn);
    NVIC_SetPriority(EXT_INT2_IRQn, 1);
    while(1)
    {   
        if (flag)
        {
            if (count == 1)
            {
                MDR_PORTB -> RXTX |= (1 << 9);
                MDR_PORTB -> RXTX &= ~(1 << 8);
            }
            else
            {
                MDR_PORTB -> RXTX |= (1 << 8);
                MDR_PORTB -> RXTX &= ~(1 << 9);
            }
        }
        else
        {
            (count == 1)? count = 2 : count = 1;
        }
    }
    return EXIT_SUCCESS;
}


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 09:49 
Не в сети

Зарегистрирован: 2017-апр-26 14:51
Сообщения: 249
Откуда: ПКК "Миландр"
А что не работает и зачем РВ8 в альтернативной функции?

_________________
Отдел технической поддержки support@milandr.ru


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 10:16 
Не в сети

Зарегистрирован: 2019-янв-17 21:29
Сообщения: 21
Vasiliy писал(а):
А что не работает и зачем РВ8 в альтернативной функции?

Сами прерывания - то есть нажатие кнопки ничего не переключает.
PB8 в "переопределенной", потому что его главная функция это "comp_out" судя по схеме ниже.


Вложения:
MSTN-M100_v0.3_Pinout_combined.png
MSTN-M100_v0.3_Pinout_combined.png [ 2.06 МБ | Просмотров: 326 ]
Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 11:31 
Не в сети

Зарегистрирован: 2017-апр-26 14:51
Сообщения: 249
Откуда: ПКК "Миландр"
Путаница какая-то:
1 - Если PB8 управляет светодиодом, и вы хотите управлять им через регистр RXTX, то пин должен быть в функции Порта. В переопределенной функции (FUNC=(3 << 8*2)) выводом PB8 управляет TMR3_CH4N - инверсный выход 4-го канала 3-го таймера.
2 - Прерывания EXT_INT вырабатываются когда на пине логическая "1". Прерывания "перевызываются" пока вывод не опустится в 0. Вывод PD10 c кнопкой в (альтернативной функции EXT_INT2) настраивается в режим с открытым стоком (PD=1), значит снаружи он подтянут к 1?
Что происходит под отладчиком, код постоянно висит в прерывании?

Вытащил из чужого кода для EXT_INT1.
Код:
  PORT_InitTypeDef PORTAInit;
 
  RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTA, ENABLE);
  PORT_StructInit(&PORTAInit); //Load defaults

  PORTAInit.PORT_Pin = PORT_Pin_0;
  PORTAInit.PORT_OE = PORT_OE_IN;
  PORTAInit.PORT_MODE = PORT_MODE_DIGITAL;
  PORTAInit.PORT_PULL_DOWN  = PORT_PULL_DOWN_ON;
  PORTAInit.PORT_FUNC = PORT_FUNC_ALTER;
   
  PORT_Init(MDR_PORTA, &PORTAInit);

  NVIC_EnableIRQ(EXT_INT1_IRQn);
  NVIC_SetPriority(EXT_INT1_IRQn, 0);

_________________
Отдел технической поддержки support@milandr.ru


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 12:06 
Не в сети

Зарегистрирован: 2019-янв-17 21:29
Сообщения: 21
Спасибо!
С первым пунктом я разобрался.
PB10 с кнопкой у меня настроен через PD на "триггер Шмитта с включенным гистерезисом" - в коде есть сдвиг на 16.
После загрузки программы на плату - плата перестаёт видеться компьютером и постоянно мигает на ней зелёный диод. Эту проблему решаю через reset + user button и загрузку программы в первые пять секунд после этого.
P.S. в вашем коде единственные отличия в том, что регистры PWR, GFEN и PD никак не настроены, но я не думаю, что это сильно меняет ситуацию
А, ещё у вас нет строчки __enable_irq
Подтяжка вниз или вверх - можете объяснить какую для диода, а какую для кнопки?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 12:25 
Не в сети

Зарегистрирован: 2017-апр-26 14:51
Сообщения: 249
Откуда: ПКК "Миландр"
Со стоком действительно недоглядел.
Отладка падает, потому что в PB0-PB4 необходимо писать только нули, если подключение по JtagА. Подробнее -
https://startmilandr.ru/doku.php/prog:debug:mosterror#%D0%B2%D1%8B%D0%B2%D0%BE%D0%B4%D1%8B_%D1%81%D0%BE%D0%B2%D0%BC%D0%B5%D1%89%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5_%D1%81_jtag

__enable_irq не нужен.
Проверьте, что на плате на выводе PB10 есть сигнал от кнопки.

Еще не хватает задержки, если фонарики и начнут мигать, то очень быстро. Либо, flag = 1 выставится только один раз, не планировалось ли его сбрасывать в 0 после отработки события?

Код:
MDR_PORTB -> RXTX |= (1 << 9);
MDR_PORTB -> RXTX &= ~(1 << 8);

Периферия отрабатывает медленнее чем работает ядро. Чтение-модификация-запись друг за другом может привести к некорректным результатам, по крайней мере об этом были упоминания на форуме. Лучше один раз считать значение, внести правки и затем записать.
RXTX - возвращает текущее состояние линии, первая запись еще может не переключить логический уровень, а считывание уже считает не отработанное состояние линии.

_________________
Отдел технической поддержки support@milandr.ru


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 12:45 
Не в сети

Зарегистрирован: 2019-янв-17 21:29
Сообщения: 21
Структурировал код, чтобы было более понятно что сделано.
Подключение не по jtag а по USB.
Хотелось бы узнать, как правильно записать регистры PD и PULL для двух светодиодов и кнопки?
P.S. Дописал сбрасывание в ноль в последний else
Код:
#include "main.h"
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include "MDR32Fx.h"
#include "system_MDR32F9Qx.h"
void init_PORTB(void);
void init_interruption(void);
void EXT_INT2_IRQHandler(void);
void switch_LED(void);

int State_B = 0;
int State_D = 8;
/*------------------------------------------------------------------*/
int main(void)
{
    init_PORTB();
    init_interruption();
    while(1)
    {   
        switch_LED();
    }
    return EXIT_SUCCESS;
}
/*-----------------------------------------------------------------*/
void init_PORTB(void)
{
    //Настройка порта B - зелёный диод, красный диод, кнопка
    MDR_RST_CLK -> PER_CLOCK |= (1 << 22);
    MDR_PORTB -> OE |= (1 << 8) | (1 << 9) | (0 << 10);
    MDR_PORTB -> FUNC |= (0 << 8*2) | (0 << 9*2) | (2 << 10*2);
    MDR_PORTB -> ANALOG |= (1 << 8) | (1 << 9) | (1 << 10);
    MDR_PORTB -> PULL |=
    MDR_PORTB -> PD |=
    MDR_PORTB -> PWR |= (1 << 8*2) | (1 << 9*2) | (1 << 10*2);
    MDR_PORTB -> GFEN |= (0 << 8) | (0 << 9) | (1 << 10);
}
/*----------------------------------------------------------------*/
void init_interruption(void)
{
    NVIC_EnableIRQ(EXT_INT2_IRQn);
    NVIC_SetPriority(EXT_INT2_IRQn, 0);
}
/*----------------------------------------------------------------*/
void EXT_INT2_IRQHandler(void)
{
    State_B = 1;
}
/*----------------------------------------------------------------*/
void switch_LED(void)
{
    if (State_B == 0)
    {
        switch (State_D)
        {
            case 8:
                MDR_PORTB -> RXTX &= ~(1 << 9);
                MDR_PORTB -> RXTX |= (1 << 8); 
                break;
            case 9:
                MDR_PORTB -> RXTX &= ~(1 << 8);
                MDR_PORTB -> RXTX |= (1 << 9);
                break;
        }
    }
    else
    {
        (State_D == 8)? State_D = 9 : State_D = 8;
        State_B = 0;
    }
}
/*--------------------------------------------------------------*/


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 13:04 
Не в сети

Зарегистрирован: 2009-июл-21 14:13
Сообщения: 1223
Откуда: Тула
По существу вопроса, ответ на него строго зависит от схемы включения кнопки и сида, которую Вы не привели.
к теме выше: регистр PWR должен содержать не нулевые значения для используемых ног (желательно, даже на вход). С этим у Вас порядок.

_________________
сочувствующий…


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 13:47 
Не в сети

Зарегистрирован: 2019-янв-17 21:29
Сообщения: 21
Ладно, допустим с этими регистрами разберусь, но по какой причине код выше нарушает работу МК мне так и непонятно.
Может где-то зацикливается?
Или для подключения через USB должны быть другие настройки?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 15:15 
Не в сети

Зарегистрирован: 2019-янв-17 21:29
Сообщения: 21
Vasiliy писал(а):
Проверьте, что на плате на выводе PB10 есть сигнал от кнопки

Забыл ответить, что кнопка работает, если через rxtx осуществлять работу, а не через прерывание.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 15:20 
Не в сети

Зарегистрирован: 2014-июн-25 09:29
Сообщения: 99
На этих МК внешние прерывания срабатывают не по фронту, а по уровню 1. Если на такой логике делать работу с кнопкой, то пока кнопку не отпустишь, будешь сидеть в обработчике прерывания. Ну или надо запрещать прерывания сразу после попадания в обработчик, а потом через какое-то время снова разрешать их. Гораздо проще и надежней сделать периодический опрос кнопки без всяких прерываний.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 15:30 
Не в сети

Зарегистрирован: 2019-янв-17 21:29
Сообщения: 21
andelie писал(а):
На этих МК внешние прерывания срабатывают не по фронту, а по уровню 1. Если на такой логике делать работу с кнопкой, то пока кнопку не отпустишь, будешь сидеть в обработчике прерывания. Ну или надо запрещать прерывания сразу после попадания в обработчик, а потом через какое-то время снова разрешать их. Гораздо проще и надежней сделать периодический опрос кнопки без всяких прерываний.

Я просто не понимаю, почему я буду сидеть в обработчике прерывания, если я даже кнопку не могу нажать - МК "ломается" сразу и постоянно мигает зелёный.
Для меня разобраться в таймерах ещё сложнее, хотелось бы с этим закончить для начала.
Про запрет:
Вы имеете в виду написать вот так в обработчике?
Код:
void EXT_INT2_IRQHandler (void)
{
NVIC_DisableIRQ(EXT_INT2_IRQn);
State_B = 1;
}


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 15:38 
Не в сети

Зарегистрирован: 2014-июн-25 09:29
Сообщения: 99
Я имею в виду, что лучше сразу отказаться от такого подхода и вообще не применять внешние прерывания в этом МК. Считайте, что их просто нету здесь :wink:. Так получилось, что вы начали знакомство с самой неудачной стороны этого, в целом, очень хорошего МК.
Если у вас на схеме (надо на нее посмотреть) ножка с кнопкой подтянута резистором к плюсу питания, а кнопка замыкается на землю, то сразу после инициализации прерываний вы безвозвратно попадете в обработчик от внешнего прерывания, так как при отпущенной кнопке на соответствующем входе МК будет 1. Проверьте вольтметром или осциллом.


Последний раз редактировалось andelie 2019-янв-18 15:45, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 15:42 
Не в сети

Зарегистрирован: 2019-янв-17 21:29
Сообщения: 21
andelie писал(а):
Я имею в виду, что лучше сразу отказаться от такого подхода и вообще не применять внешние прерывания в этом МК. Считайте, что их просто нету здесь :wink:. Так получилось, что вы начали знакомство с самой неудачной стороны этого, в целом, очень хорошего МК.

Эх, я всё же надеялся что проблема решаема.
Мне бы хотелось хотя бы загрузить без ошибок прошивку.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-янв-18 15:51 
Не в сети

Зарегистрирован: 2014-июн-25 09:29
Сообщения: 99
Чтобы не было неприятного осадка в конце рабочей недели, предлагаю просто поморгать светодиодом :). Для этого сделать цикл, в котором зажигать и через некоторую паузу тушить светодиод. Паузу можно и без таймера пока сделать:

Код:
{
   volatile unsigned int loop;

   for (loop = 1000000; loop; loop--);

}


Начальным значением переменной можно поиграть, делая паузу больше или меньше.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 39 ]  На страницу 1, 2, 3  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB