Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Прерываени и перенос массива
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
Rom20
Пишу программу по Atmega 8 и вот какая проблема когда оп перерывание принимаю данные в масив и возвращаюсь обратно из прерываний массив оказывается пустой подсажите пожалуйста может что не так с классами памяти и в чем еще может быть проблема
Код
uint8_t a[30]; //глобальное обьявление массива
int i=0,b=0;
//прерываение по флагу RXC
ISR (USART_RXC_vect)
{
    PORTA=0x03;
    _delay_ms(200);
    a[i]=UDR;
    _delay_us(10);
    UDR=a[i];
    if (a[i]==0x0D)
    {
        UDR='\r';
        _delay_ms(1);
        UDR='\n';
        i=0;
    }
    else
    {
        i++;
        b++;
    }
}

Код
void in_1()
{
DDRA=0xFF;
while(1)
{
PORTA=0x00;
UDR=a[0];  //<<<<<вот в этом месте МК в порт ни чего не выкидывает хотя по логике должен выкинуть 0й елемент массива
if (a[i]==0x0D)
{
PORTA=0xFF;
_delay_ms(200);
}
}
}
demiurg_spb
Ну что тут можно сказать:
1. Изучите ключевое слово volatile. Можете воспользоваться поиском по форуму.
2. Убрать всяческие delay из обработчиков прерываний.
Сергей Борщ
Цитата(Rom20 @ Feb 25 2010, 07:33) *
<<<<<вот в этом месте МК в порт ни чего не выкидывает хотя по логике должен выкинуть 0й елемент массива
Если действительно "ничего не выкидывает" - значит вы либо не доходите до этого места, либо в этот момент UDR занят передачей. Вы ведь не проверяете его готовность по флагу UDRE. Вполне возможно, что он занят передачей из прерывания.
Массив тут ни при чем - если бы вы получали что-то не то - тогда надо было бы искать в массиве.

А вот тут вы передаете 0x0D дважды:
Код
    UDR=a[i];
    if (a[i]==0x0D)
    {
        UDR='\r';
Rom20
Цитата(Сергей Борщ @ Feb 25 2010, 14:58) *
Если действительно "ничего не выкидывает" - значит вы либо не доходите до этого места, либо в этот момент UDR занят передачей. Вы ведь не проверяете его готовность по флагу UDRE. Вполне возможно, что он занят передачей из прерывания.
Массив тут ни при чем - если бы вы получали что-то не то - тогда надо было бы искать в массиве.

Нет UDR не занят, выкидывая i во время прерывай я получаю его раным числу символов прешедших с пк (следовательно счетчик работает) а возвращаясь из прерывания снова пробую выкинуть i в порт я получаю ноль, отсюда вывад что значение i не переносится из прерываний отсюда могу предположить что это связано с памятью мк
_Pasha
Цитата(Rom20 @ Feb 26 2010, 06:21) *
могу предположить что это связано с памятью мк

А чего гадать, если можно листинг посмотреть?
Сергей Борщ
Цитата(Rom20 @ Feb 26 2010, 05:21) *
Нет UDR не занят, выкидывая i во время прерывай я получаю его раным числу символов прешедших с пк (следовательно счетчик работает)
Еще раз, на пальцах: запись UDR = data вовсе не означает, что в этот момент байт уже отправился. Он всего лишь записался в буфер передачи и передача началась. Буфер на два байта (об этом подробно написано в даташите). Пока первый байт не будет передан полностью, писать в буфер третий байт не имеет смысла - он будет просто проигнорирован, потому что класть его просто некуда. И об этом тоже написано в даташите. Итого - вы положили в прерывании два символа (добавив \r\n), и выйдя пытаетесь передать третий. Ну сделайте же вы проверку UDRE перед передачей или боритесь дальше с ветряными мельницами - вам жалко пары команд?
Код
while(!(UCSRA & (1<<UDRE)))
  ;
UDR=a[0];
Rom20
Цитата(_Pasha @ Feb 26 2010, 10:09) *
А чего гадать, если можно листинг посмотреть?

CODE
#include <stdio.h>
#include <stdlib.h>
#include "main.h"
#include <avr/interrupt.h>
uint8_t a[30];
uint8_t i=0,b=0;
ISR (USART_RXC_vect)
{
PORTA=0xFF;
_delay_ms(200);
a[i]=UDR;

_delay_us(10);
UDR=a[i];
_delay_ms(10);
if (a[i]=='$')
{
UDR='\r';
_delay_ms(1);
UDR='\n';
_delay_ms(1);
UDR=i+48; //<<вот в этом месте выкидывает верное значение i

}
else
{
i++;
}
}

void usart()
{
//натсраиваем скорость 19200 бот/c
UBRRL=25;
UBRRH=0;
// настраиваем приемник передатчик
UCSRB=(1<<RXEN) |(1<<TXEN)|(1<<RXCIE);
// 8 бит данных
UCSRC=(1<<UCSZ0) |(1<<UCSZ1)|(1<<URSEL);

}

void main()
{
sei();
usart();
DDRA=0x80;
while(1)
{
PORTA=0;
_delay_ms(200);
UDR=i+48; //<<здесь же i все время равно 0 и из прерываний он не пересылает значени i
_delay_ms(10);
UDR=a[i]+48;
_delay_ms(20);
PORTA=0xFF;
_delay_ms(200);
if (a[i]=='$')
{
PORTA=0xFF;
_delay_ms(200);
_delay_ms(200);
_delay_ms(200);
_delay_ms(200);
_delay_ms(200);
_delay_ms(200);
_delay_ms(200);

большинство задержек поставлено специально для отладки т.к. виду отладку по меганию светодиода
Сергей Борщ
Цитата(Rom20 @ Feb 26 2010, 10:15) *
Код
UDR=i+48; //<<здесь же i все время равно 0 и из прерываний он не пересылает значени i
И будет равно, пока вы не объявите i как volatile uint8_t i. То же самое и с a[]. Все правильно. И массивы тут не при чем.
SSerge
Комментировать исходную программу, полагаю, большого смысла нет. Вам для начала нужно отделить друг от друга два уровня в программе:
нижний - работа с регистрами UART, приём и передача отдельных байт
и верхний - работа с символьной строкой.
Ниже минимальный интерфейс в традициях языка С, аналогично функциям getchar/putchar, про них в любом учебнике написано. Это реализация самая простая, без использования прерываний (при инициализации бит RXCIE устанавливать не надо).
При желании можете реализовать работу с UART-ом по прерываниям, но начать лучше с этого и потом двигаться от простого к сложному.
CODE

#ifndef EOF
#define EOF (-1)
#endif
int Uputchar( int data )
{
while ( !( UCSRA & (1<<UDRE)) )
; // ждём готовности передатчика
return UDR = data; // записали data в регистр передатчика
// и, для бОльшей похожести на putchar(),
// возвращаем это-же значение как результат функции
}

int Ugetchar( void )
{
if ( UCSRA & (1<<RXC) )
return UDR; // возвращаем байт, принятый приёмником
else
return EOF; // если приёмник ничего пока не принял, то возвращаем EOF
}

Теперь, пользуясь только Ugetchar(), принимаете символы один за другим и собираете из них строку.
Что с этой строкой дальше делать - это уже Ваша забота.
Для вывода тоже используете только Uputchar(), и нет необходимости на этом уровне задумываться как работает UART.
Rom20
Цитата(Сергей Борщ @ Feb 26 2010, 11:08) *
Ну сделайте же вы проверку UDRE перед передачей или боритесь дальше с ветряными мельницами - вам жалко пары команд?
Код
while(!(UCSRA & (1<<UDRE)))
;
UDR=a[0];

Делал проверку UDRE как вы и писали а результата не было ни какого, вот и забил на нее, вот только щас вы ответили на мой вопрос что переменные и масив мне надо было обьявит при помощи volatile uint8_t вот где у меня была ошибка, буду проверять надеюсь сработает
demiurg_spb
Цитата(Rom20 @ Feb 26 2010, 13:36) *
только щас вы ответили на мой вопрос что переменные и масив мне надо было обьявит при помощи volatile uint8_t
Я Вам об этом сразу сказал...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.