Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: внешние прерывания. помогите плз
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
123kill12
CODE
#include <intrinsics.h>
#include <stdio.h>
#include <nxp/iolpc1766.h>

#include "board.h"

#pragma section=".intvec"
#define FCCO_FREQ (300UL MHZ)
#define CCKL_DIV (3UL)
#define FCCLK_FREQ (FCCO_FREQ/CCKL_DIV)
#define FPCLK_FREQ (FCCLK_FREQ/4)
#define PCLK FPCLK_FREQ

volatile Int8U LedsState;
Int32U Reg;

void InitClock(void)
{
// 1. Init OSC
SCS_bit.OSCRANGE = 0;
SCS_bit.OSCEN = 1;
// 2. Wait for OSC ready
while(!SCS_bit.OSCSTAT);
// 3. Disconnect PLL
PLL0CON_bit.PLLC = 0;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
// 4. Disable PLL
PLL0CON_bit.PLLE = 0;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
// 5. Select source clock for PLL
CLKSRCSEL_bit.CLKSRC = 1; // Selects the main oscillator as a PLL clock source.
PCLKSEL0 = PCLKSEL1 = 0; // other peripherals 100/4 = 25MHz
// 6. Set PLL settings 300 MHz
PLL0CFG_bit.MSEL = 25-1;
PLL0CFG_bit.NSEL = 2-1;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
// 7. Enable PLL
PLL0CON_bit.PLLE = 1;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
// 8. Wait for the PLL to achieve lock
while(!PLL0STAT_bit.PLOCK);
// 9. Set clk divider settings
CCLKCFG = 3-1; // 1/3 Fpll
// 10. Connect the PLL
PLL0CON_bit.PLLC = 1;
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
}

void GpioInit(void)
{
// Set to inputs
FIO0DIR = \
FIO1DIR = \
FIO2DIR = \
FIO3DIR = \
FIO4DIR = 0;

// clear mask registers
FIO0MASK =\
FIO1MASK =\
FIO2MASK =\
FIO3MASK =\
FIO4MASK = 0;

// Reset all GPIO pins to default primary function
PINSEL0 =\
PINSEL1 =\
PINSEL2 =\
PINSEL3 =\
PINSEL4 =\
PINSEL7 =\
PINSEL8 =\
PINSEL9 = 0;
}

Int32U cnt;
void TR0int(void)
{
cnt=0;
T0MR0=FCCLK_FREQ/200;
T0MCR=3;
SETENA0 |= (1<<1);
IP0=0;
T0TCR=1;
}

void ExInt(void)
{
IO2INTENF |= (1<<10);
SETENA0 |= (1<<18);
}

void TMR0_IRQHandler (void)
{
T0IR=1;
__enable_interrupt();
cnt++;
if ( cnt >= 0x20)
{
FIO2PIN = Reg;
Reg=Reg<<1;
if(Reg>128)
{
FIO2PIN=0;
Reg=4;
}
cnt = 0;
}
CLRPEND0 |= ~(1<<1);
}

void EINT0_IRQHandler (void)
{
IO2INTCLR |= (1<<10);
__enable_interrupt(); /* handles nested interrupt */
FIO1PIN=0x80000000;
CLRPEND0 |= ~(1<<18);
}


int main(void)
{
// Flash accelerator init
FLASHCFG = (0x5UL<<12) | 0x3AUL;
// Init clock
InitClock();
#if FCCLK_FREQ < 20000000
FLASHCFG = (0x0UL<<12) | 0x3AUL;
#elif FCCLK_FREQ < 40000000
FLASHCFG = (0x1UL<<12) | 0x3AUL;
#elif FCCLK_FREQ < 60000000
FLASHCFG = (0x2UL<<12) | 0x3AUL;
#elif FCCLK_FREQ < 80000000
FLASHCFG = (0x3UL<<12) | 0x3AUL;
#elif FCCLK_FREQ < 100000000
FLASHCFG = (0x4UL<<12) | 0x3AUL;
#endif
Reg=4;
// Init GPIO
GpioInit();
ExInt();
TR0int();


// Init LEDs
FIO2DIR = 0x000000ff;
FIO1DIR = 0xF0000000;


while (1)
{ /* Loop forever */

}
}


пограмма написана на подобие примеров IAR. работает все кроме внешнего прерывания.
вроде бы все сделал правильно. EINT0 приходится на 10 ножку P2 и флаг разрешения внешнего прерывания 0 находиться на 18 бите регистра разрешений прерываний.
в обработчике прерыванию ставлю брейк поинт и нечего нет(((

(у меня MT-link)
zltigo
Программы нужно начинать писать с пяти, максимум с 10 строчек. Причем писать самому, а не копипастить какие-то примеры. И все получится.
DpInRock
Причина неработы - невнимательный копипаст.(Пару-тройку нужных процедур не хватат).
И по моему имху - вообще ничего не должно работать. По крайней мере прерывания - не должны.
123kill12
но они работают.
я раньше не работал с ARM вообще. поэтому и спрашиваю может что забыл какой нить флаг.
с прерываниями не сложно настроил и разрешил. таймер пашит, а int0 нет.



zltigo
QUOTE (123kill12 @ Jul 11 2010, 01:14) *
но они работают.

Только в Ваших грезах sad.gif. DpInRock прав - не могут работать прерывания, поскольку они, как минимум, запрещены. Остальную белиберду вообще читать не имеет смысла.

123kill12
да не наяву. я наблюдаю на плате как диодики моргают.

киньте примерный код как запустить внешнее прерывание.
toweroff
Цитата(123kill12 @ Jul 11 2010, 03:23) *
киньте примерный код как запустить внешнее прерывание.

а как кинуть в мозг даташит и перевести в С, ASM или на чем там у Вас?
123kill12
я и делал по даташиту. брал пример через дебаг разбирал что куда и зачем пишется и потом свое писал. тока у меня на плате есть int0 кнопка, а пример у IAR для int2. а с таймерами все работало.
toweroff
бегло так по коду
а чего это прерывания разрешаются в самих прерываниях?
Код
void TMR0_IRQHandler (void)
{
  T0IR=1;
  __enable_interrupt();
  cnt++;
  if ( cnt >= 0x20)

Код
void EINT0_IRQHandler (void)
{
  IO2INTCLR |= (1<<10);
  __enable_interrupt();       /* handles nested interrupt */
zltigo
QUOTE (123kill12 @ Jul 11 2010, 02:23) *
да не наяву. я наблюдаю на плате как диодики моргают.

Тогда не постите исходники не имеющие отношения к реальности.
123kill12
void TR0int(void)
{
cnt=0;
T0MR0=FCCLK_FREQ/200; установливаем MR0
T0MCR=3; разрешение прерывания если MR0 и TC совпадают и сброс TC
SETENA0 |= (1<<1); ISER0 записываем 1 в 1 разряд что соответствует разрешению прерывания от timer0
IP0=0; тут не стал нечего придумывать. поставил ноль для всех прерываний
T0TCR=1; TCR нулевой бить ставил м в 1 чтоб запустить таймер на счет
}


void TMR0_IRQHandler (void)
{
T0IR=1; регистр прерываний. сбрасываем наше самое прерывание по сравнению
__enable_interrupt(); это единственное что я не понял, но сча закоментил и без него работало
cnt++;

CLRPEND0 |= ~(1<<1); записываем в ICPR0 1 в первый разряд
}
таймер так работает( __enable_interrupt(); и без этой строчки)

void ExInt(void)
{
IO2INTENF |= (1<<10); устанавливаем прерывание IntEnF
SETENA0 |= (1<<18); ISER0 записываем 1 в 18 разряд что соответствует разрешению прерывания от int0
}


void EINT0_IRQHandler (void)
{
IO2INTCLR |= (1<<10); очищаем 10 пин intClr
__enable_interrupt(); это единственное что я не понял, но сча закоментил и без него работало
FIO1PIN=0x80000000;
CLRPEND0 |= ~(1<<18); записываем в ICPR0 1 в 18 разряд
}

нет.


но потом вспомнил что у lpc17xx есть прерывания на портах P0 и P2. которые настраиваются но обработка их в int3. может я как раз так настроил а обрабатывать пытаюсь в int0??
и переделал
void ExInt(void)
{
IO2INTENF |= (1<<10);
SETENA0 |= (1<<21);
}

void EINT3_IRQHandler (void)
{
IO2INTCLR |= (1<<10);
// __enable_interrupt(); /* handles nested interrupt */
FIO1PIN=0x80000000;
CLRPEND0 |= ~(1<<21);
}

и заработало. алилуя

но возвращаемся в простым int0-int2. как из настроить?


demiurg_spb
Цитата(123kill12 @ Jul 11 2010, 12:20) *
void EINT0_IRQHandler (void)
{
IO2INTCLR |= (1<<10); очищаем 10 пин intClr
__enable_interrupt(); это единственное что я не понял, но сча закоментил и без него работало
FIO1PIN=0x80000000;
CLRPEND0 |= ~(1<<18); записываем в ICPR0 1 в 18 разряд
}

Комментарии написаны там где не надо и их нет где надо.
Пока не привыкли стоит одуматься...
ПС оформляйте ваши посты в соответствии с общепринятыми здесь нормами -
выделяйте исходники в секции кода [ code ] ВАШИ ИСХОДНИКИ [ /code ] (пробелы внутри квадратных скобок не нужны)
DpInRock
Не поленился (хотя это и очень трудно - папка с иаром очень долго у меня открывается) посмотреть реальные исходники.
Общее и у ваших и оригинальных конечно есть. Но этого недостаточно.

Воин. Будь внимателен при контрол-с контрол-в.

Могу дать совет. берете первую строчку исходника и задаете себе вопрос - "а нафига она нужна". После ответа, переходите к следущей строчке. И так до конца файла. Гарантирую полный успех.
(Я лично языка Си не знаю и только такой подход помогает таки составлять работающие программы на этом языке).
sergeeff
Цитата(DpInRock @ Jul 11 2010, 14:47) *
(Я лично языка Си не знаю и только такой подход помогает таки составлять работающие программы на этом языке).


Во, блин, до чего народ дошел!
Wano
Скажите,а в каком месте заносится указатель функции прерывания? Или в LPC17 всё не так как в LPC2?
123kill12
регистры прерываний у них разные. у меня книжка по LPC2000 и там другое чем в даташите на LPC17xx.


перечитал даташит и нашел нужную главу по внешние прерывание
Код

void ExInt(void)
{
  SETENA0_bit.SETENA18=1;
  EXTINT_bit.EINT0=1;
  EXTMODE_bit.EXTMODE0=0;
  EXTPOLAR_bit.EXTPOLAR0=0;
  PINSEL4_bit.P2_10=0x01;
}

void EINT0_IRQHandler (void)
{
  if( Reg2==0x40000000)
  {
    Reg2=Reg2>>1;
  }
  FIO1PIN=Reg2;
  Reg2=Reg2>>1;
  if (Reg2<0x10000000)
  {
    Reg2=0x80000000;
  }
  CLRPEND0_bit.CLRPEND18=0;
}



работает. но что то не так сделал с сбросом прерывания. оно после срабатывания постоянно вызывается(((
123kill12
перечитал даташит и нашел в чем накасячил.
EXTINT геристр перрываний содержит EINT0 - чтобы сбросить его, следует программно записать в него 1.
Код
  
void ExInt(void)
{
  SETENA0_bit.SETENA18=1;
  EXTMODE_bit.EXTMODE0=1;
  EXTPOLAR_bit.EXTPOLAR0=0;
  PINSEL4_bit.P2_10=0x01;
}

void EINT0_IRQHandler (void)
{
  EXTINT_bit.EINT0=1;
  if( Reg2==0x40000000)
  {
    Reg2=Reg2>>1;
  }
  FIO1PIN=Reg2;
  Reg2=Reg2>>1;
  if (Reg2<0x10000000)
  {
    Reg2=0x80000000;
  }
  CLRPEND0_bit.CLRPEND18=1;
}


тогда вопрос зачем внешнее прерывание в носить в регистр сброса прерываний ICPR если через него сброс не происходит.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.