прерывание по нажатию кнопки AT91SAM7

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
inkHunter
Грызет канифоль
Сообщения: 287
Зарегистрирован: Сб авг 21, 2010 20:44:27
Откуда: Ростов
Контактная информация:

прерывание по нажатию кнопки AT91SAM7

Сообщение 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)
{

}


}
arm_int.rar
исходник
(31.71 КБ) 260 скачиваний
Реклама
SII
Вымогатель припоя
Сообщения: 635
Зарегистрирован: Пт янв 30, 2009 14:50:35
Откуда: Солнечногорск

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение SII »

Детально разбираться лениво, тем более на Си я, вообще говоря, не пишу (хотя прямо сейчас именно этим и занимаюсь, но это громадное исключение из правила :) ). Но пару замечаний и прочих мыслей выскажу.

1. Сначала следует полностью инициализировать контроллер прерываний (установить необходимые адреса обработчиков и т.п.), а потом уже разрешать прерывания на устройстве (в данном случае на ПИОА). Хотя проблем здесь возникнуть не должно, но лучше придерживаться этого правила, чтобы потом не ломать голову при отладке: вдруг по какой-то причине конкретная линия прерываний на контроллере будет разрешена, а обработчика ещё нет? Разрешите прерывание на устройстве -- и сразу получите прерывание на контроллере, которое указывает незнамо куда...

2. Поскольку прерывание ловим от кнопки, нужна подтяжка. Обычно кнопка нормально разомкнутая и замыкается на землю; в этом случае требуется подтяжка к питанию. Можно использовать внешний резистор, можно включить подтяжку внутри самого микроконтроллера. Включена ли она в данном случае -- вопрос (хотя по умолчанию вроде включена; кстати, у PUSR или как его, который показывает, есть подтяжка или нет, значения инверсные, насколько помню).

3. Есть ещё такая вещь, как общая маска внешних прерываний (в CPSR). Вполне может быть, что на входе в майн() прерывания запрещены именно этой маской. Следует после настройки всего разрешить их, ну а как -- надо смотреть доку на компилятор и библиотеку. В Кейле вроде __enable_irq().
Реклама
Аватара пользователя
romazan
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Чт май 21, 2009 13:54:07
Откуда: Москва
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение romazan »

В какой среде пишешь?
inkHunter
Грызет канифоль
Сообщения: 287
Зарегистрирован: Сб авг 21, 2010 20:44:27
Откуда: Ростов
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение inkHunter »

romazan писал(а):В какой среде пишешь?
Keil uVision4
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
romazan
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Чт май 21, 2009 13:54:07
Откуда: Москва
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение 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);
}
Как-то так
Последний раз редактировалось romazan Ср авг 03, 2011 23:52:58, всего редактировалось 3 раза.
Реклама
Аватара пользователя
romazan
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Чт май 21, 2009 13:54:07
Откуда: Москва
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение romazan »

Прерывание будет срабатывать при подтягивании вывода irq0 на землю
Реклама
Arlleex
Друг Кота
Сообщения: 4435
Зарегистрирован: Сб мар 07, 2009 20:44:36

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение 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);
}
Не умеешь - не берись, но не взявшись не научишься...
Аватара пользователя
romazan
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Чт май 21, 2009 13:54:07
Откуда: Москва
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение 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
Аватара пользователя
romazan
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Чт май 21, 2009 13:54:07
Откуда: Москва
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение romazan »

если уж хочется сокращений то можно просто:
#define pPIOA AT91C_BASE_PIOA
inkHunter
Грызет канифоль
Сообщения: 287
Зарегистрирован: Сб авг 21, 2010 20:44:27
Откуда: Ростов
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение 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
Arlleex
Друг Кота
Сообщения: 4435
Зарегистрирован: Сб мар 07, 2009 20:44:36

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение 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);
}
Не умеешь - не берись, но не взявшись не научишься...
inkHunter
Грызет канифоль
Сообщения: 287
Зарегистрирован: Сб авг 21, 2010 20:44:27
Откуда: Ростов
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение 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= ....
Arlleex
Друг Кота
Сообщения: 4435
Зарегистрирован: Сб мар 07, 2009 20:44:36

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение 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.
Не умеешь - не берись, но не взявшись не научишься...
inkHunter
Грызет канифоль
Сообщения: 287
Зарегистрирован: Сб авг 21, 2010 20:44:27
Откуда: Ростов
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение inkHunter »

*AT91C_PIOA_OER = LED_MASK;
и
AT91PS_PIO pPIO = AT91C_BASE_PIOA;
pPIO->PIO_OER = LED_MASK; это одно и тоже, только по разному написано... какая разница как писать ???!!! если Вы имели это ввиду ..
Аватара пользователя
romazan
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Чт май 21, 2009 13:54:07
Откуда: Москва
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение romazan »

указатель на структуру писать обязательно. Работать по другому не будет...
Я дальше ваш код не смотрел.
а вот это туфта в чистом виде
Victor Gordienko подправте код под свой процессор, у меня просто под рукой был datasheet на мой at91sam7x
inkHunter
Грызет канифоль
Сообщения: 287
Зарегистрирован: Сб авг 21, 2010 20:44:27
Откуда: Ростов
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение 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);
}
Аватара пользователя
romazan
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Чт май 21, 2009 13:54:07
Откуда: Москва
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение 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;
Аватара пользователя
romazan
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Чт май 21, 2009 13:54:07
Откуда: Москва
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение romazan »

Что-то автор пропал. Тут еще такая фишка есть. Я так понял можно обрабатывать прерывания от любой ножки. Надо в регист макси прерывания порта установить нужные единицы(номера выводов) и обрабатывать прерывания от порта. В нем читаем статус регист прерывания порта(определяем какая ножка сработала) и выполняем нужные действия.

Когда домой приеду, код небольшой сварганю и выложу сюда тогда.
inkHunter
Грызет канифоль
Сообщения: 287
Зарегистрирован: Сб авг 21, 2010 20:44:27
Откуда: Ростов
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение 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



Вы еще говорили "Когда домой приеду, код небольшой сварганю и выложу сюда тогда."
Аватара пользователя
romazan
Потрогал лапой паяльник
Сообщения: 335
Зарегистрирован: Чт май 21, 2009 13:54:07
Откуда: Москва
Контактная информация:

Re: прерывание по нажатию кнопки AT91SAM7

Сообщение 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
у меня at91sam7x256

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

Вернуться в «Микроконтроллеры и ПЛИС»