|
USART на АTmega48, не работает |
|
|
|
Dec 9 2008, 16:27
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 22-09-08
Пользователь №: 40 380

|
Доброго времени суток. Значит так, собрал платку на 48 Атмеге, работает, необходимо отправлять данные на ПК... Как топорный вариант выбрал COM-порт. Для этого была взята схемка MAX232, ну вобщем всё по книжке... Однако, не получается даже сделать простешего зеркала=/. При этом ситуация следующая: - Атмега работает от внешнего кварца в 20 МГц; - скорость - не важно, пробовал на многих, ни на одной не работает... - МАХ рабочий, тупо закорачивал ноги - сигнал возвращался тут же... - если оциллографом смотреть на ногах самой Атмеги, то приходит всегда то, что нужно, а в ответ уходит какая-то ересь... (в моём случае это 0x80) Ну вот собственно код: Код #include <avr/io.h> #include <avr/interrupt.h>
#define FOSC 20000000 // Clock Speed #define BAUD 2400 #define MYUBRR FOSC/16/BAUD-1
void USART_Init (unsigned int);
volatile unsigned char buff;
ISR (USART_RX_vect, ISR_BLOCK) { buff=UDR0; while ( !( UCSR0A & (1<<UDRE0)) ); UDR0 = buff; }
ISR (USART_TX_vect, ISR_BLOCK) { buff=0; }
void main( void ) { sei(); USART_Init(MYUBRR); for(;;); }
void USART_Init(unsigned int ubrr) { UBRR0H = (unsigned char)(ubrr>>8); UBRR0L = (unsigned char)ubrr;
UCSR0B |= (1<<RXCIE0); UCSR0B |= (1<<TXCIE0);
UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
UCSR0C = (1<<USBS0)|(3<<UCSZ00); } Может быть кварц слишком быстрый? Но по даташиту ограничения нету на его частоту никаких... Спасибо.
Сообщение отредактировал NikitoS-86 - Dec 9 2008, 16:29
|
|
|
|
|
 |
Ответов
|
Dec 10 2008, 09:07
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 22-09-08
Пользователь №: 40 380

|
Значится так... 1) Всем спасибо, поскольку полезной инфы для себя ещё подчерпнул... 2) Правы оказались товарищи Палыч и man with no name, сегодня первым делом прочитал, что было написано в ветке и за место 20 Мгц поставил 2,5 Мгц (как деление на 8) - всё заработало... Для меня если честно стало сюрпризом... Поясню почему - когда прошивал фьюзы - был абсолютно уверен, что если выбрать в закладке фьюзов в последней строке что-то типа внешнего тактового источника и нажать програм, то всё будет как надо... Как видно я ошибался... Разве это не так? К тому же теперь я не доберусь до фьюзов никак, поскольку у меня на руках mk2, то теперь он мне не даст без СТК500 добраться до фьюзов... Или я опять ошибаюсь?
3) Теперь по поводу моего кода... Да, прерывание по передаче, возможно и лишнее, как и цикл, но тогда у меня встаёт вопрос - а как обойтись без цикла (ну который у меня под вайлом идёт)? Просто когда мне надо переслать 1 байт - всё замечательно, он ушёл и бог с ним... А если целый пакет? Не получится ли так, что просто в цикле будет так, что следующий пакет будет наступать на пятки предыдущему? Или может тут как раз стоит подумать о прерывании по окончании передачи?
4) И ещё вопрос... Ситуация - надо отослать массив данных, например, short (2 байта)... Мне достаточно написать: UDDR0=Mass[i] и он сам поймёт, что надо просто тупо запихать сначала первый байт инта, потом второй? Или же надо самостоятельно ему поочереди запихнуть сначала первый байт, потом второй?
Спасибо.
Сообщение отредактировал NikitoS-86 - Dec 10 2008, 09:15
|
|
|
|
|
Dec 10 2008, 09:53
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(NikitoS-86 @ Dec 10 2008, 11:07)  когда прошивал фьюзы - был абсолютно уверен, что если выбрать в закладке фьюзов в последней строке что-то типа внешнего тактового источника и нажать програм, то всё будет как надо... Вот-вот... тоже попался на удочку визардов. Пользуюсь AVReal. Читаю описание всех фузов, пишу .bat с командной строкой, абсолютно уверен, что "оно само" ничего лишнего не сделает. Цитата(NikitoS-86 @ Dec 10 2008, 11:07)  Просто когда мне надо переслать 1 байт - всё замечательно, он ушёл и бог с ним... А если целый пакет? В данном случае целый пакет вы не получите, потому что уже сидите в прерывании приема. Если надо переслать несколько байт, то используют промежуточный буфер в озу и прерывание по освобождению UDR, а не по окончанию передачи. Примерно вот так (код для меги8, но идея понятна): CODE #define TX_BUFFER_SIZE 8 uint8_t volatile TxHead; uint8_t volatile TxTail; uint8_t TxPool[TX_BUFFER_SIZE];
void send_byte(unsigned char byte) { uint8_t Tmp = TxHead; while((uint8_t)(Tmp - TxTail) >= (uint8_t) TX_BUFFER_SIZE) ; // buffer full, wait
TxBuffer[ Tmp ] = Byte; Tmp = (Tmp + 1) & (TX_BUFFER_SIZE - 1); TxHead = Tmp; UCSRB |= (1<<UDRIE); }
void send_str(PGM_P string) { char c; while( (c = pgm_read_byte(string++)) != '\x0' ) { send_byte( c ); } } void send_str_P(char * string) { char c; while( (c = *string++) != '\x0' ) { send_byte( c ); } }
ISR(USART_UDRE_vect) { UCSRB &= ~(1<<UDRIE); sei(); { uint8_t Tmp = TxTail; UDR = TxBuffer[ Tmp ]; Tmp = (Tmp + 1) & (TX_BUFFER_SIZE - 1) TxTail = Tmp; if(Tmp != TxHead) // more data pending in buffer { UCSRB |= (1<<UDRIE); } } } или, в простейшем случае, без прерываний: Код void send_byte(uint8_t Byte) { while(!(UCSRA & (1<<UDRE))); UDR = Byte; } В любом случае ожидание должно происходить вне обработчика прерывания. Цитата(NikitoS-86 @ Dec 10 2008, 11:07)  Не получится ли так, что просто в цикле будет так, что следующий пакет будет наступать на пятки предыдущему? Или может тут как раз стоит подумать о прерывании по окончании передачи? В случае "эха" - не получится. И прерывание по освобождению UDR. Прерывание об окончании передачи используется для другого - например, для отключения передатчика в RS485. Цитата(NikitoS-86 @ Dec 10 2008, 11:07)  4) И ещё вопрос... Ситуация - надо отослать массив данных, например, short (2 байта)... Мне достаточно написать: UDDR0=Mass[i] и он сам поймёт, что надо просто тупо запихать сначала первый байт инта, потом второй? Или же надо самостоятельно ему поочереди запихнуть сначала первый байт, потом второй? Конечно самостоятельно. В вашей строке он запихнет только i-тый элемент массива. Можно написать универсальную функцию: Код void send_block(void const *ptr, uint8_t size) { while(size--) { send_byte(*ptr++); } }
void test() { unsigned char Mass[2]; unsigned short Short;
send_block(Mass, sizeof(Mass)); send_block(&Short, sizeof(Short)); }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 10 2008, 13:11
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 22-09-08
Пользователь №: 40 380

|
Цитата(Сергей Борщ @ Dec 10 2008, 12:53)  В данном случае целый пакет вы не получите, потому что уже сидите в прерывании приема. /.../или, в простейшем случае, без прерываний: Код void send_byte(uint8_t Byte) { while(!(UCSRA & (1<<UDRE))); UDR = Byte; } В любом случае ожидание должно происходить вне обработчика прерывания. Вот тут я несколько не понял, что мне мешает, сидя в прерывании, отсылать ему всё, что у меня так накопилось... Как раз таки вставив код "простейшего случая" у меня получилось отослать всё своё, правда конечно реализация выборки байтов элементов массива была ужасная... Я просто не понимаю в чем тут подводный камень? Цитата Конечно самостоятельно. В вашей строке он запихнет только i-тый элемент массива. Можно написать универсальную функцию: Код void send_block(void const *ptr, uint8_t size) { while(size--) { send_byte(*ptr++); } }
void test() { unsigned char Mass[2]; unsigned short Short;
send_block(Mass, sizeof(Mass)); send_block(&Short, sizeof(Short)); } А вот тут меня смущает только одно: цикл while мы проходим по уменьшению размера в байтах, что логично, однако send_byte при этом идёт по увеличению указателя... В случае массива разве не получится, что тут же перепрыгнем на второй элемент массива? Спасибо.
|
|
|
|
|
Dec 10 2008, 13:22
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(NikitoS-86 @ Dec 10 2008, 15:11)  Вот тут я несколько не понял, что мне мешает, сидя в прерывании, отсылать ему всё, что у меня так накопилось... Да потому что не накопится ничего. Неоткуда накопиться - вы уже сидите в прерывании приема. Значит все остальные прерывания запрещены. Цитата(NikitoS-86 @ Dec 10 2008, 15:11)  Как раз таки вставив код "простейшего случая" у меня получилось отослать всё своё, правда конечно реализация выборки байтов элементов массива была ужасная... Я просто не понимаю в чем тут подводный камень? В том, что этот код выполняется не из прерывания, а из основной программы. Все другие прерывания, в том числе и прерывание приема, в этом случае работают. Цитата(NikitoS-86 @ Dec 10 2008, 15:11)  А вот тут меня смущает только одно: цикл while мы проходим по уменьшению размера в байтах, что логично, однако send_byte при этом идёт по увеличению указателя... В случае массива разве не получится, что тут же перепрыгнем на второй элемент массива? Керниган и Ритчи. "Язык программирования С". Второе издание. Ссылку найдете через Гугля. Прочитать от начала до конца. Потом внимательно перечитать раздел 2.8 "Операторы инкремента и декремента". Обратите внимание, чем отличаются постфиксная и префиксная формы этих операторов. P.S. Да, там у меня ошибка, должно быть Код void send_block(void const *buffer, uint8_t size) { uint8_t *ptr = (uint8_t *)buffer; while(size--) { send_byte(*ptr++); } }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
Сообщений в этой теме
NikitoS-86 USART на АTmega48 Dec 9 2008, 16:27 Палыч Вы уверены что вот это будет подсчитано правильно
... Dec 9 2008, 16:36 NikitoS-86 Цитата(Палыч @ Dec 9 2008, 19:36) Вы увер... Dec 9 2008, 16:43  Палыч Цитата(NikitoS-86 @ Dec 9 2008, 19:4... Dec 9 2008, 16:49   NikitoS-86 Цитата(Палыч @ Dec 9 2008, 19:49) Ну, поч... Dec 9 2008, 16:53 Сергей Борщ Цитата(NikitoS-86 @ Dec 9 2008, 18:2... Dec 9 2008, 16:54 Палыч Может fuse CKDIV8 остался запрограммирован? С заво... Dec 9 2008, 17:01 Палыч Цитата(Сергей Борщ @ Dec 9 2008, 19:54) С... Dec 9 2008, 17:07 NikitoS-86 Цитата(Сергей Борщ @ Dec 9 2008, 19:54) С... Dec 9 2008, 17:10  Сергей Борщ Цитата(NikitoS-86 @ Dec 9 2008, 19:1... Dec 9 2008, 17:44 gormih Цитата(Сергей Борщ @ Dec 9 2008, 19:54) А... Dec 9 2008, 17:37  Сергей Борщ Цитата(gormih @ Dec 9 2008, 19:37) А если... Dec 9 2008, 17:49   gormih Цитата(Сергей Борщ @ Dec 9 2008, 20:49) И... Dec 9 2008, 18:13 man with no name попробуйте uart включать после окончательной иници... Dec 9 2008, 17:04 gormih AVR CALCULATOR
Хватит уже п**у мучать, товарищи... Dec 9 2008, 17:46 =GM= Цитата(NikitoS-86 @ Dec 9 2008, 16:2... Dec 9 2008, 19:01
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|