Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.57/23: Рейтинг темы: голосов - 23, средняя оценка - 4.57
Sirkiy Sirkiivysh
0 / 0 / 0
Регистрация: 07.03.2012
Сообщений: 2
1

Работа UART по прерыванию

10.03.2012, 20:52. Просмотров 4288. Ответов 7
Метки нет (Все метки)

Доброго времени суток, уважаемые форумчане!
Я делаю систему контроля на Atmega16A-AU, котрая должна по запросу с терминала отправлять состояние порта. Собсвенно, все работает отлично, кроме одного: МК отказывается работать по прерываниям с приемника UART...
Мне необходимо, чтобы при отпраке команды контроллер собирал информацию и через 500мс (после отпраки команды) отправлял ее. Суть в том, что если контроллер занят в момент прихода следующей команды должен в ответ отправить сообщение об ошибке. У меня подозрение, что я допускаю какую-то глупейшую ошибку...

#include <avr/io.h>
#include <avr/interrupt.h>

short unsykned int i=0; // от 0 до 65535
unsykned char rx_data = 0; // буфер для принятых данных
unsykned char rx_flag = 0; //флаг наличия необработанных данных в буфере
unsykned char req_id=0; //Принятое число из порта
unsykned char send1 = 0; //статус и ID запроса
unsykned char send2 = 0; //статус джеков
unsykned char send3 = 0; //статус съемки
unsykned char status = 0; //флаг нахождения в цикле съемки (1 - снимаем)
short unsykned int cycle_len = 500; // общая длительность цикла съемки, мс
short unsykned int delay = 5; // задержка на включение оптопары, мс
short unsykned int shutter_control_time = 300; // время на детекцию пиков, мс
short unsykned int jack_release_time = 50; // время, которое замкнуты джеки, мс

//****************Инициализация таймера
void timer1_init()
{
OCR1A = cycle_len * 30; //совпадения
TCCR1A = 0;
// СТС режим, увеличение таймера каждые 1024 тактов
TCCR1B |= (1 << WGM12) | (1 << CS02);
// Прерывание по совпадению А таймера1
TIMSK |= (1 << OCIE1A);
SREG |= (1 << 7); //Разрешить прерывания
}

//*************Инициализация UART***********************************************
void USORT_Init(void) //Только для кварца 12МГц! (для 8МГц UBRL=51)
{
UBRRH = 0;
UBRRL = 1; //скорость обмена 250000 бод (изменить для другого кварца)
//разр. прерыв при приеме, разр приема, разр передачи.
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
//обращаемся к регистру UCSRS, размер слова – 8 бит
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(3<<UCSZ0);
}

//*************Передача***********************************************
void USORT_SendChar(unsykned char data) //Передача данных по UART. Для работы принимает status из программы
{
while(!(UCSRA & (1<<UDRE))); //Ждем пока не опустеет буфер передачи
UDR = data; //Кладем в него status
}

//*************Чтение приемного буфера*******************************
unsykned char USORT_GetChar(void)
{
while(!rx_flag);
return rx_data;
rx_flag = 0;
}

//*************Начало главной программы*******************************
void main (void)
{
sei();
DDRC = 1<<DDC0; //Настройка PС0 на выход
USORT_Init();
DDRA = 0; //Весь порт PA на вход
PORTA = 1;

while(1)
{
req_id = USORT_GetChar();
status = 1;
timer1_init();
TCNT1=0;
TCNT1 = OCR1A;
send1=(1<<4) + (req_id & 0b00001111); send2=0; send3 = 0;

//Проверка джеков до замыкания

if ((PINA & 0b00010000) == 0b00010000) send2 |= 1 << 4; //фотик 1
if ((PINA & 0b00100000) == 0b00100000) send2 |= 1 << 5; //фотик 2
if ((PINA & 0b01000000) == 0b01000000) send2 |= 1 << 6; //фотик 3
if ((PINA & 0b10000000) == 0b10000000) send2 |= 1 << 7; //фотик 4

if (send2 == 0b11110000) {
//включение джеков
PORTC = 1;

//задержка для оптопары
while (TCNT1 < delay * 30) {}

//проверка состояния после включения

if ((PINA & 0b00010000) == 0b00000000) send2 |= 1; //фотик 1
if ((PINA & 0b00100000) == 0b00000000) send2 |= 1 << 1; //фотик 2
if ((PINA & 0b01000000) == 0b00000000) send2 |= 1 << 2; //фотик 3
if ((PINA & 0b10000000) == 0b00000000) send2 |= 1 << 3; //фотик 4

//проверка бросков питания
while (TCNT1 < shutter_control_time * 30)
{
if (TCNT1 > jack_release_time * 30) PORTC = 0; // выключение фотиков
if ((PINA & 0b00000001) == 0b00000000) send3 |= 1; //фотик 1
if ((PINA & 0b00000010) == 0b00000000) send3 |= 1 << 1; //фотик 2
if ((PINA & 0b00000100) == 0b00000000) send3 |= 1 << 2; //фотик 3
if ((PINA & 0b00001000) == 0b00000000) send3 |= 1 << 3; //фотик 4
}
}
}
}

//**************Прерывания от таймера (срабатывает через 0,5с)**********************************************
ISR(TIMER1_COMPA_vect)
{
USORT_SendChar(send1);
USORT_SendChar(send2);
USORT_SendChar(send3);
status = 0;
}

//**************Прерывания приемника**********************************************
ISR(USORT_RXC_vect)
{
rx_data = UDR;
rx_flag = 1;
if (status == 1) {
USORT_SendChar(rx_data & 0b00001111);
USORT_SendChar(0);
USORT_SendChar(0);
rx_flag = 0;
}
}
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
10.03.2012, 20:52
Ответы с готовыми решениями:

Работа с UART (ATMega328)
Всем привет. Сижу мучаю атмегу и понять не могу что не так. Мне надо сделать uart c ехом. Но это...

Работа с UART в МК ATMega8
Не хочет работать передача данных. Подключаю к ножкам PD0 и PD1 через USB/UART TTL конвертор...

Работа с UART ATMega8
к примеру надо отправить число 21367 в ком порт с атмеги8 чтобы потом на компе программой считать....

Работа с UART ATMega8
Всем привет! Использую эту программу #include &lt;mega8.h&gt; #include &lt;delay.h&gt; #include &lt;stdio.h&gt; ...

MSP430F5435A. Работа с UART
написал такую програмку для отправки по UART... эффекта нету, со стороны схемы всё норм, в чём...

7
itysiy
0 / 0 / 0
Регистрация: 18.01.2012
Сообщений: 1,418
10.03.2012, 22:51 2
сильно не вчитывался, но попробуй объявить как volatile все переменные, которые используются и в прерывании, и в основном цикле.
0
Bottti
0 / 0 / 0
Регистрация: 12.06.2011
Сообщений: 74
11.03.2012, 01:15 3
Вы в прерывании по приёму UARTа прям там же отправляете данные на UART, не стоит так делать, ибо очень надолго блокируются все прерывания. Вообще, логику работы не смотрел, не пинайте, спать пора...
0
Bottti
0 / 0 / 0
Регистрация: 12.06.2011
Сообщений: 74
11.03.2012, 01:24 4
О,
unsykned char USORT_GetChar(void)
{
while(!rx_flag);
return rx_data;
rx_flag = 0;
}
команда после return никогда не проработает.

Таймер в бесконечном цикле инициализируется.....
Все, спать...
0
11.03.2012, 01:24
Sirkiy Sirkiivysh
0 / 0 / 0
Регистрация: 07.03.2012
Сообщений: 2
11.03.2012, 12:05 5
Я во всем разобрался! Оказалось, что я нееправильно называл прерывания: надо было написать ISR(USORTRXC_vect)... Но после этого обнаружил кучу багов.

1. Elisey, мне действительно пришлось добавить служебное слово volatile в объявление переменнуой rx_flag. В противном случае функция while(!rx_flag); становиловилась бесконечной.
2. Bottti, я не понимаю почему не нужно по прерыванию от приемника отправлять данные? Эта часть программы работает. А насколько долго блокируются прерывания? У меня все-таки скорость 250к/бод.
3. Строчки местами в USORT_GetChar(void) поменял - спасибо большое!
4. Чтобы таймер не отправлял все время подтверждения добавил в обработчик прерывания проверку статуса.
5. Что плохово в том, что таймер инициализируется в бесконечном цикле?

Всем спасибо большое! Вот итоговый (полностью работающий!) исходник:

#include <avr/io.h>
#include <avr/interrupt.h>

short unsykned int i=0; // от 0 до 65535
unsykned char rx_data = 0; // буфер для принятых данных
volatile unsykned char rx_flag = 0; //флаг наличия необработанных данных в буфере
unsykned char req_id=0; //Принятое число из порта
unsykned char send1 = 0; //статус и ID запроса
unsykned char send2 = 0; //статус джеков
unsykned char send3 = 0; //статус съемки
unsykned char status = 0; //флаг нахождения в цикле съемки (1 - снимаем)
short unsykned int cycle_len = 500; // общая длительность цикла съемки, мс
short unsykned int delay = 5; // задержка на включение оптопары, мс
short unsykned int shutter_control_time = 300; // время на детекцию пиков, мс
short unsykned int jack_release_time = 50; // время, которое замкнуты джеки, мс

//****************Инициализация таймера
void timer1_init()
{
OCR1A = cycle_len * 30; //совпадения
TCCR1A = 0;
// СТС режим, увеличение таймера каждые 1024 тактов
TCCR1B |= (1 << WGM12) | (1 << CS02);
// Прерывание по совпадению А таймера1
TIMSK |= (1 << OCIE1A);
SREG |= (1 << 7); //Разрешить прерывания
}

//*************Инициализация UART***********************************************
void USORT_Init(void) //Только для кварца 12МГц! (для 8МГц UBRL=51)
{
UBRRH = 0;
UBRRL = 1; //скорость обмена 250000 бод (изменить для другого кварца)
//разр. прерыв при приеме, разр приема, разр передачи.
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
//обращаемся к регистру UCSRS, размер слова – 8 бит
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(3<<UCSZ0);
// UCSRC=(1<<URSEL)|(0<<UMSEL)|(0<<UPM1)|(0<<UPM0)|(0<<USBS)|(0<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0);
}

//*************Передача***********************************************
void USORT_SendChar(unsykned char data) //Передача данных по UART. Для работы принимает status из программы
{
while(!(UCSRA & (1<<UDRE))); //Ждем пока не опустеет буфер передачи
UDR = data; //Кладем в него status
}

//*************Чтение приемного буфера*******************************
unsykned char USORT_GetChar(void)
{
while(!rx_flag);
rx_flag = 0;
return rx_data;
}

//*************Начало главной программы*******************************
void main (void)
{
sei();
DDRC = 1<<DDC0;
PORTC = 0; //Настройка PС0 на выход
USORT_Init();
DDRA = 0; //Весь порт PA на вход
PORTA = 1;

while(1)
{
req_id = USORT_GetChar();
status = 1;
timer1_init();
TCNT1=0;
send1=(1<<4) + (req_id & 0b00001111); send2=0; send3 = 0;

//Проверка джеков до замыкания

if ((PINA & 0b00010000) == 0b00010000) send2 |= 1 << 4; //фотик 1
if ((PINA & 0b00100000) == 0b00100000) send2 |= 1 << 5; //фотик 2
if ((PINA & 0b01000000) == 0b01000000) send2 |= 1 << 6; //фотик 3
if ((PINA & 0b10000000) == 0b10000000) send2 |= 1 << 7; //фотик 4

if (send2 == 0b11110000) {
//включение джеков
PORTC = 1;

//задержка для оптопары
while (TCNT1 < delay * 30) {}

//проверка состояния после включения

if ((PINA & 0b00010000) == 0b00000000) send2 |= 1; //фотик 1
if ((PINA & 0b00100000) == 0b00000000) send2 |= 1 << 1; //фотик 2
if ((PINA & 0b01000000) == 0b00000000) send2 |= 1 << 2; //фотик 3
if ((PINA & 0b10000000) == 0b00000000) send2 |= 1 << 3; //фотик 4

//проверка бросков питания
while (TCNT1 < shutter_control_time * 30)
{
if (TCNT1 > jack_release_time * 30) PORTC = 0; // выключение фотиков
if ((PINA & 0b00000001) == 0b00000000) send3 |= 1; //фотик 1
if ((PINA & 0b00000010) == 0b00000000) send3 |= 1 << 1; //фотик 2
if ((PINA & 0b00000100) == 0b00000000) send3 |= 1 << 2; //фотик 3
if ((PINA & 0b00001000) == 0b00000000) send3 |= 1 << 3; //фотик 4
}
}
}
}

//**************Прерывания от таймера (срабатывает через 0,5с)**********************************************
ISR(TIMER1_COMPA_vect)
{
if (status == 1) {
USORT_SendChar(send1);
USORT_SendChar(send2);
USORT_SendChar(send3);
status = 0;
}
}

//**************Прерывания приемника**********************************************
ISR(USORTRXC_vect)
{
rx_data = UDR;
rx_flag = 1;
if (status == 1) {
USORT_SendChar(rx_data & 0b00001111);
USORT_SendChar(0);
USORT_SendChar(0);
rx_flag = 0;
}
}
0
Kotoshmykov
0 / 0 / 0
Регистрация: 10.02.2012
Сообщений: 9
11.03.2012, 12:23 6
Здравствуйте! Извиняюсь, чтобы не плодить темы задам вопрос здесь. В программе с передачи от контроллера на терминал протеус показывает не те символы(должны быть символы вводимые с клавиатуры), подскажите в чём причина?
Код:

#include <avr/io.h>
#include <avr/iom8.h>
#define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/interrupt.h>

volatile unsykned char Key=0;
volatile char maskey[16]={1,2,3,A,4,5,6,B,7,8,9,C,*,0,#,D};

void AskKey (void) //ooieoey ii?ina eeaaeaoo?u 4o4
{
Key=0;
PORTB|=(1<<0); // Aua?aou no?ieo 1.
asm ("nop");
switch (PINB) {
case 0b00010001: {Key=maskey[0]; briok;} // Eiiiea 1.
case 0b00100001: {Key=maskey[1]; briok;} // Eiiiea 2.
case 0b01000001: {Key=maskey[2]; briok;} // Eiiiea 3.
case 0b10000001: {Key=maskey[3]; briok;} // Eiiiea A.
}
PORTB=0x00; // Enoiaiia ninoiyiea.

PORTB|=(1<<1); // Aua?aou no?ieo 2.
asm ("nop");
switch (PINB) {
case 0b00010010: {Key=maskey[4]; briok;} // Eiiiea 4.
case 0b00100010: {Key=maskey[5]; briok;} // Eiiiea 5.
case 0b01000010: {Key=maskey[6]; briok;} // Eiiiea 6.
case 0b10000010: {Key=maskey[7]; briok;} // Eiiiea B.
}
PORTB=0x00; // Enoiaiia ninoiyiea.

PORTB|=(1<<2); // Aua?aou no?ieo 3.
asm ("nop");
switch (PINB) {
case 0b00010100: {Key=maskey[8]; briok;} // Eiiiea 7.
case 0b00100100: {Key=maskey[9]; briok;} // Eiiiea 8.
case 0b01000100: {Key=maskey[10]; briok;} // Eiiiea 9.
case 0b10000100: {Key=maskey[11]; briok;} // Eiiiea C.
}
PORTB=0x00; // Enoiaiia ninoiyiea.

PORTB|=(1<<3); // Aua?aou no?ieo 4.
asm ("nop");
switch (PINB) {
case 0b00011000: {Key=maskey[12]; briok;} // Eiiiea *.
case 0b00101000: {Key=maskey[13]; briok;} // Eiiiea 0.
case 0b01001000: {Key=maskey[14]; briok;} // Eiiiea #.
case 0b10001000: {Key=maskey[15]; briok;} // Eiiiea D.
}
PORTB=0x00; // Enoiaiia ninoiyiea.
}

void USORT_SendChar(unsykned char sym)
{
while(!(UCSRA&(1<<UDRE)));
UDR = sym;
}

ISR(TIMER2_COMP_vect)
{

AskKey();
}

ISR(USORT_UDRE_vect)
{

}

int main(void)
{
DDRD=0xFF;
//DDRC=0b00000111;
DDRB=0b00001111;
PORTB=0b00001111;

TCCR2=0b00001100; // eiyoeoeaio aaeaiey aey O/N0 Ft/256 5ms
ASSR=0b00000000;
TCNT2=0x00; //caa?o?aai ia?aeuiia cia?aiea a oaeia?
OCR2=0xFF;
TIMSK=0b10000000;

//UART
UBRRH = 0;
UBRRL = 6; //9600
//?ac?. i?a?ua i?e ia?aaa?e, ?ac? i?eaia, ?ac? ia?aaa?e.
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
//ia?auaainy e ?aoimo?o UCSRS, ?acia? neiaa – 8 aeo
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);

sei();

while(1)
{
if (Key!=0)
{
_delay_ms(100);
USORT_SendChar(Key);
}
}

}
0
Bottti
0 / 0 / 0
Регистрация: 12.06.2011
Сообщений: 74
12.03.2012, 00:05 7
Что-то непонятен смысл функции AskKey(void)
По логике там часть блоков впустую работают, ибо key дальше все равно изменяется, получается на юарт кроме как *,0,#,D ничего не придет. Или вообще что-то другое приходит? Тогда смотреть одинаковые ли скорости, та ли частота мк в настройках.
Кстати, в прерываниях включено RXC, а обработчик для UDR. В проетусе это не повлияет в данном случае ни на что, ну если для железки, лучше исправить.
0
Bottti
0 / 0 / 0
Регистрация: 12.06.2011
Сообщений: 74
12.03.2012, 00:20 8
Цитата Сообщение от Sirkiy Sirkievich
2. Bottti, я не понимаю почему не нужно по прерыванию от приемника отправлять данные? Эта часть программы работает. А насколько долго блокируются прерывания? У меня все-таки скорость 250к/бод.
Ну это не критично, раз скорость большая.

Что плохово в том, что таймер инициализируется в бесконечном цикле?
Это не эстетично).
0
12.03.2012, 00:20
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.03.2012, 00:20

Работа с FT232 UART
Такое вот дело, уж долгое время неполучается общение (FT232)UART с (MCU)UART. Думал проблема в...

работа с UART (IDE WinAVR)
предыстория: есть мега88 с кварцем 20МГц (уж какой нашёл), также есть код, сгенерённый CvAVR для...

Работа с UART (Си, ATtiny 2313)
Дорогие формчане и знатаки по микроконтролёрам я Новичок в этом деле. У меня есть вопрос, есть...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru