реклама на сайте
подробности

 
 
> Настройка прерываний в LPC1778, с полного нуля
ДЕЙЛ
сообщение Jul 7 2014, 19:43
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Листинг в общих чертах такой:

Инициализация и настройка тактирования

1: U0IER|=0x4; //Разрешение прерывания по приёму байта в RX
2: __enable_irq(); //Разрешаем прерывания (CMSIS)
3: __set_BASEPRI(0xFFFFFFFF); //Разрешаем все прерывания (CMSIS)
4: NVIC_EnableIRQ(UART0_IRQn); //Разрешение прерывания UART0 (CMSIS)

while(1)
{
Циклическая отправка данных на ПК
}


5: __irq void UART0_IRQ1(void)
{
for (k=0; k<200; k++)
{
FIO1SET=0x2000000; //Подёргаем ножкой 200 раз
FIO1CLR=0x2000000;
}
}


Хочу сделать так, чтобы при появлении байта в буфере приёма UART вызывалось прерывание. Вот с этим вызовом прерывания проблема и пока не знаю, с какой стороны к ней подходить. Вопросы такие:
1. Правильно ли я выполнил настройки? (строки 1-4)
в строке 4 в качестве параметра функции передаётся UART0_IRQn. Что значит эта n? Её так и нужно оставлять или вместо n нужно какое-то число стаить? Хотя компилятор ругается.

2. Правильно ли я оформил обработчик прерывания? (строка 5). В этой строке пробовал писать название функции от UART0_IRQ1 ло UART0_IRQ10. Компилятор не ругался, но и толку никакого не было, на осциллографе не видел дёрганий ножки после отправки байта с ПК.
На что влияет выделенное число?


Данные в буфер приёма однозначно приходят правильные с ПК.
На скрине моя программа в сыром виде. При нажатии кнопки "ТЕСТОВАЯ" с COM-порта отправляется 1 байт 0xAA, который я вижу принятым программой от МК (выделено). Т.е. с приёмом нормально всё, но не совсем удобно каждый раз смотреть на буфер, куда удобнее считывать из него байт по прерыванию. Ну и с настройкой прерываний разобраться нужно.

И ещё имеется такой регистр
//SETENA0=0xFFFFFFFF;
В описании написано, что каждый бит этого регистра разрешает или запрещает соответствующее прерывание. Как понять, к какому прерыванию относится конкретный бит?

Сообщение отредактировал ДЕЙЛ - Jul 7 2014, 19:46
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
menzoda
сообщение Jul 8 2014, 08:33
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 13-09-12
Пользователь №: 73 530



Цитата(ДЕЙЛ @ Jul 7 2014, 23:43) *
Правильно ли я оформил обработчик прерывания? (строка 5). В этой строке пробовал писать название функции от UART0_IRQ1 ло UART0_IRQ10. Компилятор не ругался, но и толку никакого не было, на осциллографе не видел дёрганий ножки после отправки байта с ПК.
На что влияет выделенное число?


Не правильно. Ни на что не влияет. Для Cortex-M обработчики всех прерываний задаются статически, обычно в startup.s-файле, но можно это сделать и в C-файле. В стандартном startup.s обработчики помечены модификатором WEAK. Не вдаваясь в подробности это значит, что если определить свою функцию с таким же именем, то будет вызываться она, иначе будет вызываться обработчик по умолчанию, который в startup.s.

Значит, тебе нужно заглянуть в этот файл и посмотреть имя интересующего тебя обработчика, никаких гаданий и переборов тут не нужно. Когда найдешь имя - реализуешь свою функцию с таким же именем, это и будет обработчиком. Никаких __irq не нужно, это было актуально для ARM7 (но все же лучше уточни, а то я давно этим занимался, может уже позабыл чего). Естественно можно при желании периименовать обработчик как душе угодно, можно выкинуть обработчик по умолчанию, можно еще много чего, но это наверное уже не входит в твои планы.

Ах, да. В прерывании возможно потребуется сбрасывать флаг прерывания. Я тут тоже не очень помню, в документацию лезть неохота, посмотри сам.

Сообщение отредактировал menzoda - Jul 8 2014, 10:04
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Jul 8 2014, 11:05
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Цитата(menzoda @ Jul 8 2014, 12:33) *
Никаких __irq не нужно, это было актуально для ARM7 (но все же лучше уточни, а то я давно этим занимался, может уже позабыл чего)

как тогда указать компилятору, что эта функция выполняется по прерыванию?
в startup откопал вот эту функцию: UART0_IRQHandler
Только в модуле UART0 несколько источников прерываний, скрин описаний в прикреплённом файле.
Как программе указать, что прерывание нужно именно после приёма байта?

Цитата(ДЕЙЛ @ Jul 7 2014, 23:43) *
И ещё имеется такой регистр
//SETENA0=0xFFFFFFFF;
В описании написано, что каждый бит этого регистра разрешает или запрещает соответствующее прерывание. Как понять, к какому прерыванию относится конкретный бит?

по этому вопросу откопал в даташите:

Сообщение отредактировал ДЕЙЛ - Jul 8 2014, 11:07
Эскизы прикрепленных изображений
Прикрепленное изображение
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Jul 8 2014, 14:29
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(ДЕЙЛ @ Jul 8 2014, 14:05) *
как тогда указать компилятору, что эта функция выполняется по прерыванию?
в startup откопал вот эту функцию: UART0_IRQHandler
Только в модуле UART0 несколько источников прерываний, скрин описаний в прикреплённом файле.
Как программе указать, что прерывание нужно именно после приёма байта?


Вот пример обработчика прерывания UART0 LPC17xx.
Название обработчика совпадает с названием в стартапе UART0_IRQHandler.
В ARM на одну переферию обычно идёт один вектор прерываний.
А там по флагам разгребают в чём именно причина прерывания.
Вам ранее уже много чего рассказали про прерывания в CORTEX-M3. И всё что было рассказано сущая правда.
Для приёма байта нужно разрешить прерывания IER_RBR и IER_RLS. Посмотрите внимательно на обработчик прерывания и будет ясно почему именно эти прерывания.

С отправкой данных интересней. Если Вы разрешите IER_THRE прерывание, то никогда не вылезите из обработчика т.к. пустой передающий буффер будет непрерывно генерить прерывание. Поэтому для передачи данные закидывают в буффер и разрешают IER_THRE. а в обработчике прерывания мониторят наличие данных на передачу и запрещают IER_THRE, когда данных больше нет.

CODE
void UART0_IRQHandler (void)
{

unsigned char IIRValue, LSRValue;
volatile unsigned char Dummy;


IIRValue = U0IIR;
IIRValue >>= 1; /* skip pending bit in IIR */
IIRValue &= 0x07; /* check bit 1~3, interrupt identification */
if ( IIRValue == IIR_RLS ) /* Receive Line Status */
{
LSRValue = U0LSR;
/* Receive Line Status */
if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
{
/* There are errors or break interrupt */
/* Read LSR will clear the interrupt */
Dummy = U0RBR; /* Dummy read on RX to clear interrupt, then bail out */


NVIC_ClrPend(NVIC_UART0);
return;
}

if ( LSRValue & LSR_RDR ) /* Receive Data Ready */
{
/* If no error on RLS, normal ready, save into the data buffer. */
/* Note: read RBR will clear the interrupt */

//приём завершён, ложим байт в фифо
Rx0Buf[Rx0Head++] = U0RBR;
if (Rx0Head >= US0_RXBUFSIZE) Rx0Head = 0;

}
}
else if ( IIRValue == IIR_RDA ) /* Receive Data Available */
{
/* Receive Data Available */

//приём завершён, ложим байт в фифо
Rx0Buf[Rx0Head++] = U0RBR;
if (Rx0Head >= US0_RXBUFSIZE) Rx0Head = 0;

}
else if ( IIRValue == IIR_CTI ) /* Character timeout indicator */
{
/* Character Time-out indicator */
/* Bit 9 as the CTI error */
}
else if ( IIRValue == IIR_THRE ) /* THRE, transmit holding register empty */
{
/* THRE interrupt */
LSRValue = U0LSR; /* Check status in the LSR to see if valid data in U3THR or not */
if ( LSRValue & LSR_THRE )
{

//передача байта завершена
if (Tx0Tail != Tx0Head)
{
U0THR = Tx0Buf[Tx0Tail++];
if (Tx0Tail >= US0_TXBUFSIZE) Tx0Tail = 0;
}
else
{
//запрещаем прерывания по опустошению передающего буффера
U0IER &= ~IER_THRE;
}

}
}

NVIC_ClrPend(NVIC_UART0);
return;
}
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Jul 8 2014, 20:54
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Цитата(mempfis_ @ Jul 8 2014, 18:29) *
Вот пример обработчика прерывания UART0 LPC17xx.

Для меня это уже следующий этап, сейчас нужно как-то зайти в этот обработчик. Насчёт источников прерывания тоже понятно - аналогия с MSP430, где двум портам соответствуют два вектора, а в обработчике уже разбор битов ножек.

Упростил свою программу до такоо вида, оставив саму суть вопроса:

CODE
#include "C:\10062014LPC\iolpc1778.h"
#include "C:\10062014LPC\src\inc\LPC17xx.h"
int N, pin;
void main(void)
{

//INIT
//Настройка ножек
IOCON_P1_25=0; //PIO
FIO1DIR=0x2200000; //Выходы PIN1_25, PIN1_11
PCONP|=0x8; //Питание модуля UART0
IOCON_P0_02=0x1; //На ножках переферийный модуль (TX, RX)
IOCON_P0_03=0x1;
FIO0DIR=0x4+0x8;

//Настройка тактирования
SCS|=0x20; //подключение осциллятора
while(!(SCS&0x40)){} //ожидание запуска

PCLKSEL=1;
CLKSRCSEL|=1;
U0LCR|=0x83; //разрешение доступа к делителю
U0DLL=0x14; //настройка делителя
U0LCR&=~0x80; //запрет доступа к делителю

U0IER|=0x1+0x4; //Разрешение прерываний UART0
__set_PRIMASK(0); //Разрешение
__set_FAULTMASK(0); //всех прерываний
__set_BASEPRI(0); //Отключение маскирования
NVIC_EnableIRQ(UART0_IRQn); //Enable IRQ UART0 (ISER0=32)

pin=0x200000; //изначально импульсы на ножке P1.11



while(1)
{
FIO1CLR=pin; //0
FIO1SET=pin; //1
FIO1CLR=pin; //0
}
}

void UART0_IRQHandler(void)
{
N=U0RBR; //прочитаем на всякий случай принятое

pin=0x200000+0x2000000; //после выхода из прерывания
//точно такие же импульсы появляются на P1.25

NVIC_ClearPendingIRQ(UART0_IRQn);
return;
}

По моей задумке при выполнении этой программы на одной ножке кристалла (P1.11) в бесконечном цикле генерируются прямоугольные импульсы. Эта часть работает, что наблюдаю на осциллографе. При отправке одного байта с ПК в прерывании выполняется операция, после которой в основной программе в бесконечном цикле точно такие же импульсы формируются на второй ножке(P1.25), т.е. на осциллографе второй канал станет рисовать копию первого сигнала. Это будет оворить о том, что был выполнен вход в прерывание, выполнились соответствующие действия и нормально вышли в главную программу.

Но пока не работает - при отправке байта процессор зависает и бесконечный цикл главной программы останавливается, импульсы не формируются.
Байт отправляется правильно, т.к. его визуально наблюдал при приёме данных, но эту процедуру в коде убрал, настройки тактирования оставил без изменений.

Что я не досмотрел в коде?

Цитата(menzoda @ Jul 8 2014, 12:33) *
Ах, да. В прерывании возможно потребуется сбрасывать флаг прерывания. Я тут тоже не очень помню, в документацию лезть неохота, посмотри сам.

вот это не глянул, утром почитаю и вечером попробую, рабочий ноут на проверку диска поставил, но всё же хотелось бы почитать критику моего кода со стороны более опытных коллег sm.gif

Сообщение отредактировал ДЕЙЛ - Jul 8 2014, 20:47
Прикрепленные файлы
Прикрепленный файл  10062014LPC.rar ( 920.41 килобайт ) Кол-во скачиваний: 11
 
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- ДЕЙЛ   Настройка прерываний в LPC1778   Jul 7 2014, 19:43
- - ДЕЙЛ   Сегодня утром вчитался получше в описание регистра...   Jul 8 2014, 05:58
|- - menzoda   Цитата(ДЕЙЛ @ Jul 8 2014, 15:05) как тогд...   Jul 8 2014, 12:50
|- - menzoda   Критиковать пока особо нечего, это же просто набро...   Jul 9 2014, 05:43
- - ДЕЙЛ   Прогнал в отладчике через JTAG пошагово. Запусти...   Jul 9 2014, 19:40
|- - menzoda   Все логично. Она застряла в бесконечном цикле обра...   Jul 10 2014, 05:05
|- - ДЕЙЛ   Цитата(menzoda @ Jul 10 2014, 09:05) Эй, ...   Jul 10 2014, 17:58
- - ДЕЙЛ   Вечером попробую. Интересно узнать ещё мнение насч...   Jul 10 2014, 06:36
- - ДЕЙЛ   Продолжаю начинать осваивать LPC. Читаю про вложен...   Jul 15 2014, 19:30
- - menzoda   КодNVIC_EnableIRQ(UART0_IRQn); //Enable IR...   Jul 16 2014, 06:12
|- - ДЕЙЛ   Цитата(menzoda @ Jul 16 2014, 10:12) КодN...   Jul 16 2014, 07:12
|- - menzoda   Цитата(ДЕЙЛ @ Jul 16 2014, 11:12) Данная ...   Jul 16 2014, 11:40
|- - ДЕЙЛ   Цитата(menzoda @ Jul 16 2014, 15:40) Хм, ...   Jul 16 2014, 12:30
- - ДЕЙЛ   На другом форуме сказали посмотреть регистры уровн...   Jul 17 2014, 07:32
- - ДЕЙЛ   С уровнями приоритетов разобрался. Ошибка была в т...   Jul 17 2014, 17:45
- - menzoda   В даташите про него ничего не будет, надо искать в...   Jul 17 2014, 17:59
- - ДЕЙЛ   Цитата(menzoda @ Jul 17 2014, 21:59) В да...   Jul 18 2014, 03:26
- - menzoda   Никакая. Точнее так, можно сообщить библиотеке вре...   Jul 18 2014, 05:07


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 29th July 2025 - 02:30
Рейтинг@Mail.ru


Страница сгенерированна за 0.01475 секунд с 7
ELECTRONIX ©2004-2016