Страница 1 из 2
прерывание по нажатию кнопки AT91SAM7
Добавлено: Чт июл 21, 2011 18:58:36
inkHunter
Помогите с прерыванием по нажатию кнопки (только начинаю разбираться с АРМ ....)
#include <at91sam7s256.h>
#define LED0 (1<<0) // PA0
#define LED1 (1<<1) // PA1
#define LED2 (1<<2) // PA2
#define LED3 (1<<3) // PA3
#define LED4 (1<<27) // PA27
#define LED5 (1<<28) // PA28
#define LED6 (1<<29) // PA29
#define LED7 (1<<30) // PA30
#define SW0 (1<<19) // PA19
#define SW1 (1<<20) // PA20
#define SW2 (1<<15) // PA15
#define SW3 (1<<14) // PA14
int ex_int_handler ()
{
AT91S_PIO *pPIO = AT91C_BASE_PIOA;
pPIO->PIO_CODR = LED0; // LED0 ON
}
int main()
{
AT91S_PIO *pPIO = AT91C_BASE_PIOA;
AT91S_PMC *pPMC = AT91C_BASE_PMC;
AT91S_AIC *pAIC = AT91C_BASE_AIC;
pPIO->PIO_OER = LED0; // Output Enable Register
pPIO->PIO_SODR = LED0; // LED0 OFF
pPMC->PMC_PCER = 1 << AT91C_ID_PIOA; // Peripheral Clock Enable Register
pPIO->PIO_IER = SW0; // Interrupt Enable Register PA19 SW0
pPIO->PIO_IMR = SW0; // Interrupt Mask Register PA19 SW0
pAIC->AIC_SVR[AT91C_ID_PIOA] = (unsigned int)ex_int_handler;
pAIC->AIC_IECR = (1 << AT91C_ID_PIOA);
while (1)
{
}
}
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Пт июл 22, 2011 03:49:35
SII
Детально разбираться лениво, тем более на Си я, вообще говоря, не пишу (хотя прямо сейчас именно этим и занимаюсь, но это громадное исключение из правила

). Но пару замечаний и прочих мыслей выскажу.
1. Сначала следует полностью инициализировать контроллер прерываний (установить необходимые адреса обработчиков и т.п.), а потом уже разрешать прерывания на устройстве (в данном случае на ПИОА). Хотя проблем здесь возникнуть не должно, но лучше придерживаться этого правила, чтобы потом не ломать голову при отладке: вдруг по какой-то причине конкретная линия прерываний на контроллере будет разрешена, а обработчика ещё нет? Разрешите прерывание на устройстве -- и сразу получите прерывание на контроллере, которое указывает незнамо куда...
2. Поскольку прерывание ловим от кнопки, нужна подтяжка. Обычно кнопка нормально разомкнутая и замыкается на землю; в этом случае требуется подтяжка к питанию. Можно использовать внешний резистор, можно включить подтяжку внутри самого микроконтроллера. Включена ли она в данном случае -- вопрос (хотя по умолчанию вроде включена; кстати, у PUSR или как его, который показывает, есть подтяжка или нет, значения инверсные, насколько помню).
3. Есть ещё такая вещь, как общая маска внешних прерываний (в CPSR). Вполне может быть, что на входе в майн() прерывания запрещены именно этой маской. Следует после настройки всего разрешить их, ну а как -- надо смотреть доку на компилятор и библиотеку. В Кейле вроде __enable_irq().
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Вт июл 26, 2011 00:26:39
romazan
В какой среде пишешь?
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Вс июл 31, 2011 19:53:18
inkHunter
romazan писал(а):В какой среде пишешь?
Keil uVision4
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Ср авг 03, 2011 23:01:52
romazan
Код: Выделить всё
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <AT91SAM7X256.h>
#include "..\ETHERUS.h"
char a;
void int_sw(void) __irq{
a=!a;
if(a){
*AT91C_PIOB_CODR = LED1;
}
else{
*AT91C_PIOB_SODR = LED1;
}
AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_AIC->AIC_ISR;
}
int main(void)
{
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA)|(1 << AT91C_ID_PIOB);
*AT91C_PIOB_PER = LED_MASK;
*AT91C_PIOB_OER = LED_MASK;
*AT91C_PIOB_SODR = LED_MASK;
*AT91C_PIOA_ASR = (1<<30);
*AT91C_PIOA_PPUER = (1<<30);
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_IRQ0] = AT91C_AIC_PRIOR_LOWEST;
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_IRQ0] = (unsigned int) int_sw;
AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_IRQ0);
while(1);
}
Как-то так
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Ср авг 03, 2011 23:06:53
romazan
Прерывание будет срабатывать при подтягивании вывода irq0 на землю
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Чт авг 04, 2011 03:13:46
Arlleex
А где объявления переменных?? Вот этот код вставьте в соответствующее место и попробуйте.
Код: Выделить всё
int main(void)
{
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; // pointer to PIO data structure
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; // pointer to PMC data structure
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC; // bla bla bla
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA)|(1 << AT91C_ID_PIOB);
*AT91C_PIOB_PER = LED_MASK;
*AT91C_PIOB_OER = LED_MASK;
*AT91C_PIOB_SODR = LED_MASK;
*AT91C_PIOA_ASR = (1<<30);
*AT91C_PIOA_PPUER = (1<<30);
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_IRQ0] = AT91C_AIC_PRIOR_LOWEST;
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_IRQ0] = (unsigned int) int_sw;
AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_IRQ0);
while(1);
}
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Чт авг 04, 2011 07:52:12
romazan
А нафига оно надо?
Код: Выделить всё
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; // pointer to PIO data structure
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; // pointer to PMC data structure
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC; // bla bla bla
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Чт авг 04, 2011 10:14:32
romazan
если уж хочется сокращений то можно просто:
#define pPIOA AT91C_BASE_PIOA
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Чт авг 04, 2011 15:51:06
inkHunter
ничего не работает (((
int main(void)
{
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA)|(1 << AT91C_ID_PIOB); // это если дальше PIOA не нужно ?
*AT91C_PIOB_PER = LED_MASK; // почему PIO_B если дальше PIOA
*AT91C_PIOB_OER = LED_MASK;
*AT91C_PIOB_SODR = LED_MASK;
*AT91C_PIOA_ASR = (1<<30); // почему 1<<30 если IRQ0 - PA20
*AT91C_PIOA_PPUER = (1<<30); // если кнопка уже подтянута то это не нужно ?
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_IRQ0] = AT91C_AIC_PRIOR_LOWEST;
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_IRQ0] = (unsigned int) int_sw;
AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_IRQ0);
while(1);
}
работаю с EVBsam7s вот :
#define LED0 (1<<0) // PA0
#define LED1 (1<<1) // PA1
#define LED2 (1<<2) // PA2
#define LED3 (1<<3) // PA3
#define LED4 (1<<27) // PA27
#define LED5 (1<<28) // PA28
#define LED6 (1<<29) // PA29
#define LED7 (1<<30) // PA30
#define SW0 (1<<19) // PA19
#define SW1 (1<<20) // PA20
#define SW2 (1<<15) // PA15
#define SW3 (1<<14) // PA14
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Чт авг 04, 2011 21:35:36
Arlleex
romazan писал(а):А нафига оно надо?
Код: Выделить всё
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; // pointer to PIO data structure
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; // pointer to PMC data structure
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC; // bla bla bla
Это указатели на структуру. Она нужна.
Виктор, вы пробовали использовать мой метод?? Вернее код, который я привел вам в качестве примера?
Код: Выделить всё
int main(void)
{
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; // pointer to PIO data structure
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; // pointer to PMC data structure
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC; // bla bla bla
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOB; // pointer to PIO data structure
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA)|(1 << AT91C_ID_PIOB);
*AT91C_PIOB_PER = LED_MASK;
*AT91C_PIOB_OER = LED_MASK;
*AT91C_PIOB_SODR = LED_MASK;
*AT91C_PIOA_ASR = (1<<30);
*AT91C_PIOA_PPUER = (1<<30);
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_IRQ0] = AT91C_AIC_PRIOR_LOWEST;
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_IRQ0] = (unsigned int) int_sw;
AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_IRQ0);
while(1);
}
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Чт авг 04, 2011 21:59:29
inkHunter
А какая разница все то самое ... и наверно глупо писать AT91PS_PIO pPIO = AT91C_BASE_PIOA; а дальше писать не используя pPIO, *AT91C_PIOB_PER = LED_MASK;
если объявили переменную структуры как pPIO:
AT91PS_PIO pPIO = AT91C_BASE_PIOA;
то дальше к регистру как я понимаю обращаемость через pPIO
pPIO->PIOA_SODR= ....
pPIO->PIOA_OER= ....
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Чт авг 04, 2011 22:05:46
Arlleex
указатель на структуру писать обязательно. Работать по другому не будет...
Я дальше ваш код не смотрел.
так что с теми моими 4 строчками и вашим ПЕРЕПИСАННЫМ кодом работать будет.
Вот, как у меня идет вывод на PIO, а также разрешение этого PIO, разрешение его тактирования в PMC, а также разрешение USART в PMC (вернее синхронизация):
Код: Выделить всё
#include "AT91SAM7X512.h"
int main()
{
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; // pointer to PIO data structure
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC; // pointer to PMC data structure
pPMC->PMC_PCER = (1<<AT91C_ID_PIOA && 1<<AT91C_ID_US0); // разрешаем тактирование usart и pioa
pPIO->PIO_PPUDR = (1<<AT91C_PIO_PA4); // сбрасываем подтягивающий резистор
pPIO->PIO_PER = (1<<AT91C_PIO_PA4); // Выбираем управление выводами программой
pPIO->PIO_OER = (1<<AT91C_PIO_PA4); // разрешение выхода
pPIO->PIO_CODR = (1<<AT91C_PIO_PA4); // устанавливаем линию вывода данных в уровень логического 0
pPIO->PIO_ASR = (1<<AT91C_PA0_RXD0 && 1<<AT91C_PA1_TXD0); // выбираем периферию А
pPIO->PIO_PDR = (1<<AT91C_PA0_RXD0 && 1<<AT91C_PA1_TXD0); // Выбираем управление выводами от периферии
while(1)
{;}
}
Программа прекрасно компилируется в Keil uVision 4.
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Чт авг 04, 2011 22:53:52
inkHunter
*AT91C_PIOA_OER = LED_MASK;
и
AT91PS_PIO pPIO = AT91C_BASE_PIOA;
pPIO->PIO_OER = LED_MASK; это одно и тоже, только по разному написано... какая разница как писать ???!!! если Вы имели это ввиду ..
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Пт авг 05, 2011 15:59:11
romazan
указатель на структуру писать обязательно. Работать по другому не будет...
Я дальше ваш код не смотрел.
а вот это туфта в чистом виде
Victor Gordienko подправте код под свой процессор, у меня просто под рукой был datasheet на мой at91sam7x
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Пт авг 05, 2011 18:00:30
inkHunter
romazan писал(а):указатель на структуру писать обязательно. Работать по другому не будет...
Я дальше ваш код не смотрел.
а вот это туфта в чистом виде
Victor Gordienko подправте код под свой процессор, у меня просто под рукой был datasheet на мой at91sam7x
подправил, но не работает (
#include <at91sam7s256.h>
#define LED0 (1<<0) // PA0
#define LED1 (1<<1) // PA1
#define LED2 (1<<2) // PA2
#define LED3 (1<<3) // PA3
#define LED4 (1<<27) // PA27
#define LED5 (1<<28) // PA28
#define LED6 (1<<29) // PA29
#define LED7 (1<<30) // PA30
#define SW0 (1<<19) // PA19
#define SW1 (1<<20) // PA20
#define SW2 (1<<15) // PA15
#define SW3 (1<<14) // PA14
char a;
void int_sw(void) __irq{
a=!a;
if(a){
*AT91C_PIOA_CODR = LED1;
}
else{
*AT91C_PIOA_SODR = LED1;
}
AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_AIC->AIC_ISR;
}
int main(void)
{
AT91C_BASE_PMC->PMC_PCER =(1 << AT91C_ID_PIOA);
*AT91C_PIOA_PER = LED1|SW1;
*AT91C_PIOA_OER = LED1;
*AT91C_PIOA_SODR = LED1;
*AT91C_PIOA_ASR = (1<<SW1);
//*AT91C_PIOA_PPUER = (1<<SW1);
*AT91C_PIOA_IER = SW1; // Interrupt Enable Register PA20 SW1
*AT91C_PIOA_IMR = SW1; // Interrupt Mask Register PA20 SW1
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_IRQ0] = AT91C_AIC_PRIOR_LOWEST;
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_IRQ0] = (unsigned int) int_sw;
AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_IRQ0);
while(1);
}
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Пт авг 05, 2011 20:50:36
romazan
Код: Выделить всё
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA)|(1 << AT91C_ID_PIOB);
AT91C_BASE_PIOB->PIO_PER = LED_MASK;
AT91C_BASE_PIOB->PIO_OER = LED_MASK;
AT91C_BASE_PIOB->PIO_SODR = LED_MASK;
AT91C_BASE_PIOA->PIO_ASR = (1<<30);
AT91C_BASE_PIOA->PIO_PPUER = (1<<30);
AT91C_BASE_PIOA->PIO_PDR = (1<<30);
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_IRQ0] = AT91C_AIC_PRIOR_LOWEST;
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_IRQ0] = (unsigned int) int_sw;
AT91C_BASE_AIC->AIC_IECR = (1<<AT91C_ID_IRQ0);
немного довел до ума, у меня работает в реальном устройстве.
забыл, дырявая моя голова
Код: Выделить всё
AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_PIOA->PIO_ISR;
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Сб авг 13, 2011 21:03:12
romazan
Что-то автор пропал. Тут еще такая фишка есть. Я так понял можно обрабатывать прерывания от любой ножки. Надо в регист макси прерывания порта установить нужные единицы(номера выводов) и обрабатывать прерывания от порта. В нем читаем статус регист прерывания порта(определяем какая ножка сработала) и выполняем нужные действия.
Когда домой приеду, код небольшой сварганю и выложу сюда тогда.
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Пн сен 05, 2011 22:33:20
inkHunter
Я так и не понял почему вы используете PIOB если вроде все на PIOА
у меня ошибки
ADC.c(35): error: #20: identifier "AT91C_PIOB_OER" is undefined
ADC.c(36): error: #20: identifier "AT91C_PIOB_SODR" is undefined
Вы еще говорили "Когда домой приеду, код небольшой сварганю и выложу сюда тогда."
Re: прерывание по нажатию кнопки AT91SAM7
Добавлено: Вт сен 06, 2011 14:07:47
romazan
Victor Gordienko писал(а):Я так и не понял почему вы используете PIOB если вроде все на PIOА
у меня ошибки
ADC.c(35): error: #20: identifier "AT91C_PIOB_OER" is undefined
ADC.c(36): error: #20: identifier "AT91C_PIOB_SODR" is undefined
Вы еще говорили "Когда домой приеду, код небольшой сварганю и выложу сюда тогда."
у вас at91sam7s256
у меня at91sam7
x256
Про код я совсем забыл

и как-то относительно давно это было.
Там вообщем такая соль, можно фиксировать изменения состояния на ножках и из этого определять какая кнопка изменила своё состояние - будет фиксировать нажатие и отпускание.
Есть такой регистр Interrupt Enable Register в нем выставляются значения - от каких ножек производить прерывание.
Ну так вот. Настраиваешь прерывание от PIO контроллера. В прерывании считываешь значение Interrupt Status Register(Из него будет ясно какая ножка сработала).
Далее как раз выставляешь номера ножек на которых кнопки весят.