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

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

Сообщение 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
Откуда: Солнечногорск

Сообщение SII »

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

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

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

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

Сообщение romazan »

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

Сообщение inkHunter »

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

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

Сообщение romazan »

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

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

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

Сообщение romazan »

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

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

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

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

Сообщение inkHunter »

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

Сообщение romazan »

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

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

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

Сообщение romazan »

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

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

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



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

Сообщение 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(Из него будет ясно какая ножка сработала).
Далее как раз выставляешь номера ножек на которых кнопки весят.
Контактная информация:
Закрыто

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