Начинаю изучать

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Открыл глаза
Сообщения: 40
Зарегистрирован: Ср дек 09, 2009 23:05:49

Сообщение winex »

Здравствуйте! Начинаю изучать программирование AVR. Поставил перед собой такую задачу - отобразить на светодиодах число. И передать число серез COM порт. МК - atmega128.
Написал программу на С. Просьба посмотрите и напишите свои замечания, наверняка я что-то не учел.

#include <iom128v.h>
#include <stdio.h>
#include <macros.h>
#include "delay.h"

#define b9600 47 // 7.3728MHz clock
#define b19200 23
#define b38400 11
#define b57600 7


void init_USART1(unsigned int baud)
{
UCSR1B = 0x00;
UCSR1A = 0x00;
UCSR1C = 0x0E;
UBRR1L = baud;
UBRR1H = 0x00;
UCSR1B = 0x98;
}


void main() {
int a,i;
CLI();
init_USART1(47);
DDRD = 0xFF;
PORTD = 0;
SEI();
delay_ms(2000);
PORTD = 10;
delay_ms(2000);
PORTD = 0;
UDR1 = 0x04;
a = UDR1;
}
Реклама
Опытный кот
Сообщения: 877
Зарегистрирован: Чт фев 18, 2010 13:51:56

Сообщение Murav »

Скомпили, прошей и проверь работает так как хотел или нет.

Из замечаний:

Во-первых в коде нет цикла, потому контроллер мигнёт светодиодами один раз и перейдёт в бесконечный цикл поставленный компилятором на выходе из main. Если хочешь чтобы контроллер работал постоянно нужно использовать бесконечный цикл:

Код: Выделить всё

void main()
{
	//Инициализация
	while(1) {
		//Основной код
	}
}
Во-вторых если в WinAVR(он же AVR GCC и компилятор в AVR Studio) включаешь прерывания, то нужно задать обработчик прерываний по умолчанию:

Код: Выделить всё

EMPTY_INTERRUPT(BADISR_vect);
В-третьих в регистах биты лучше указывать не в виде уже расчитаного числа а в виде выражения (1<<ИМЯ_БИТА) | (1<<ИМЯ_БИТА) | (1<<ИМЯ_БИТА) - так потом легче понять какие биты установлены в регистре. Например вместо

Код: Выделить всё

PORTD = 10;
лучше написать

Код: Выделить всё

PORTD = (1<<PD3) | (1<<PD1);
И так же что такое заголовочный файл delay.h ?
Реклама
Открыл глаза
Сообщения: 40
Зарегистрирован: Ср дек 09, 2009 23:05:49

Сообщение winex »

Спасибо за совет с битами и про цикл

Код: Выделить всё

PORTD = (1<<PD3) | (1<<PD1);
PD3 и PD1 это константы библиотечные или пользовательские?
эквивалентно ли это?

Код: Выделить всё

PORTD = (1<<3) | (1<<1);
delay.h это библиотека с задержками, взял из рабочего проекта
Нашел транзистор. Понюхал.
Сообщения: 193
Зарегистрирован: Вт авг 25, 2009 22:24:39
Откуда: Черкассы

Сообщение Twilo »

не совсем эквивалентно. константы библиотечные. это эквивалентно (1<<0b00000100) | (1<<0b00000001)
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Открыл глаза
Сообщения: 40
Зарегистрирован: Ср дек 09, 2009 23:05:49

Сообщение winex »

Во-вторых если в WinAVR(он же AVR GCC и компилятор в AVR Studio) включаешь прерывания, то нужно задать обработчик прерываний по умолчанию:

Код: Выделить всё

EMPTY_INTERRUPT(BADISR_vect);
Я почитал про прерывания, как понял они срабытывают по какому-то событию. А какое у меня тут событие, кроме прекращение передачи в УСАПП.
Если это какой-то особенный обработчик, то расскажите пожалуйста.
Реклама
Открыл глаза
Сообщения: 40
Зарегистрирован: Ср дек 09, 2009 23:05:49

Сообщение winex »

Подскажите, пожалуйста, как в AVR Studio эмулировать прерывания.

Эмулирую след. код

Код: Выделить всё

include <iom128v.h>
#include <stdio.h>
#include <macros.h>
#include "delay.h"


//******************************************************************
//*	BAUD RATE NUMBERS FOR UBRR
//******************************************************************
#define  b9600  47		// 7.3728MHz clock
#define	 b19200 23
#define	 b38400 11
#define	 b57600 7
#pragma interrupt_handler USART1_TX_interrupt:33

void USART1_TX_interrupt(void)
{
    PORTD = 0x5F;
	delay(2000);
	PORTD = 0xFF;
}

void init_USART1(unsigned int baud)
{
 UCSR1A = 0b00000000;
 UCSR1C = 0x0E;
 UBRR1L = baud; //set baud rate lo
 UBRR1H = 0x00; //set baud rate hi
 UCSR1B = 0b01001000;//разрешить прерывание при отправке, включить передатчик
}


void main() {
CLI(); 
   init_USART1(47);
   DDRD = 0xFF;
   PORTD = 0xFF;
   SEI(); 
   while(1)
   {
       delay_ms(5000);
	   UDR1 = 5;
	   a=6;
	   
   }  
   
}
В эмуляторе не наблюдаю изменение регистра порта D и UCSR1A.
Подскажите как правильно делать.
Реклама
Опытный кот
Сообщения: 877
Зарегистрирован: Чт фев 18, 2010 13:51:56

Сообщение Murav »

winex писал(а): PD3 и PD1 это константы библиотечные или пользовательские?
Они объявлены в avr\io.h , который - часть библиотеки avr-libc, в свою очередь которая входит в WinAVR. То есть это - стандартные библиотечные константы.
winex писал(а): эквивалентно ли это?

Код: Выделить всё

PORTD = (1<<3) | (1<<1);
Эквивалентно.
Только в случае регистров ввода-вывода лучше всё равно использовать имена битов: во-первых так легче понять что именно делают указаные биты, а во-вторых в других микроконтроллерах положения битов в регистрах может поменяться(хотя такое бывает редко), и в случае если биты указаны не по именам, то придётся исправлять их вручную.
Хотя в случае портов ввода-вывода можно писать и (1<<3), так как там и так понятно, что это - третий пин в порту. А вот в регистрах например USART лучше использовать имена регистров(кроме регистра скорости, где все 8 бит - одно число, а не набор флагов).
Twilo писал(а):не совсем эквивалентно. константы библиотечные. это эквивалентно (1<<0b00000100) | (1<<0b00000001)
А вот (1<<0b00000100) и (1<<3) - неэквивалентно, потому что 0b00000100 - это 4 в двоичной записи(а (1<<4) уж ни как не равно (1<<3) ). А вот (1<<0b00000001) - эквивалентно (1<<1) (0b00000001 = 1).
winex писал(а):
Во-вторых если в WinAVR(он же AVR GCC и компилятор в AVR Studio) включаешь прерывания, то нужно задать обработчик прерываний по умолчанию:

Код: Выделить всё

EMPTY_INTERRUPT(BADISR_vect);
Я почитал про прерывания, как понял они срабытывают по какому-то событию. А какое у меня тут событие, кроме прекращение передачи в УСАПП.
BADISR_vect - это обработчик для всех прерываний для которых не указан свой обработчик. А EMPTY_INTERRUPT обозначет, что обработчик пуст.
Это эквивалентно

Код: Выделить всё

ISR(BADISR_vect)
{
}
Такой обработчик нужен на случай, если какие-то прерывания окажутся включенными, а обработчиков для них не будет. В WinAVR в случае, если для прерывания нет обработчика, при его срабатывании произойдёт сброс контроллера(точнее код начнёт выполняться с нулевого адреса, а вот регистры ввода-вывода не сбросятся).
winex писал(а):Подскажите, пожалуйста, как в AVR Studio эмулировать прерывания.
Если имеется в виду симулятор в AVR Studio, то в нём прерывание сработает при наступлении соответствующего события. Только в AVR Studio эмулируется далеко не вся переферия, так что что-нибудь вполне может не работать. Лучше проверять на реальном контроллере.
winex писал(а):#pragma interrupt_handler USART1_TX_interrupt:33
void USART1_TX_interrupt(void)
Во-первых в WinAVR (и соответсвенно в AVR Studio) прерывания описываются по другому:

Код: Выделить всё

ISR(USART_TXC_VECT)
{
//обработчик прерывания
}
И если посмотришь warning'и то там скорее всего есть сообщение, что директива #pragma interrupt_handler проигнорирована.

И вообще этот код компилится?

Вообще советую сначала заставить мигать светодиод(и убедиться в том что он действительно мигает), а уже потом браться за UART.
Открыл глаза
Сообщения: 40
Зарегистрирован: Ср дек 09, 2009 23:05:49

Сообщение winex »

И вообще этот код компилится?
Да, с помощью ICC avr.
Вообще советую сначала заставить мигать светодиод(и убедиться в том что он действительно мигает), а уже потом браться за UART
С этим я уже разобрался. :)) Теперь вот хочу с ПК связать серез COM. Пробую в эмуляторе, не срабатывает. А такое объявление прерываний взял из рабочего проекта.


я могу добывить в свой проет след код

Код: Выделить всё

ISR(BADISR_vect)
{
}
именно пустая процедура, и исключить внезапные прерывания?
Нашел транзистор. Понюхал.
Сообщения: 193
Зарегистрирован: Вт авг 25, 2009 22:24:39
Откуда: Черкассы

Сообщение Twilo »

А вот (1<<0b00000100) и (1<<3) - неэквивалентно, потому что 0b00000100 - это 4 в двоичной записи(а (1<<4) уж ни как не равно (1<<3) ). А вот (1<<0b00000001) - эквивалентно (1<<1) (0b00000001 = 1).
прошу прощения, второй раз прочитал и вижу что неправильно написал. подумал о результате операции
Контактная информация:
Открыл глаза
Сообщения: 40
Зарегистрирован: Ср дек 09, 2009 23:05:49

Сообщение winex »

Код: Выделить всё

#pragma interrupt_handler interrupt_TX:33
void interrupt_TX()
{
    PORTD = 0x7F;
	//delay_ms(2000);
	PORTD = 0xFF;
	
}
Все-таки такая конструкция работает. Вот только не пойму как эмулируется передача... Вроде регистр UDR1 обнуляется, а флаг о завершении передачи не выставляется. Подскажите, может я логику не понимаю...
и еще пытаюсь сделать UCSR1A |= 0b01000000; установить флаг завершения передачи, и не устанавливается...
Последний раз редактировалось winex Вт мар 23, 2010 22:41:07, всего редактировалось 1 раз.
Опытный кот
Сообщения: 877
Зарегистрирован: Чт фев 18, 2010 13:51:56

Сообщение Murav »

winex писал(а): Все-таки такая конструкция работает.
Как ты это определил?

Можешь выложить hex-файл прошивки - я посмотрю, стала ли эта функция обработчиком прерывания.
Открыл глаза
Сообщения: 40
Зарегистрирован: Ср дек 09, 2009 23:05:49

Сообщение winex »

поменял вектор, не 33 а 32, разрешил прерывание по UDRIE1 и вошел в прерывание
Вложения
vt1.rar
(826 байт) 163 скачивания
Опытный кот
Сообщения: 877
Зарегистрирован: Чт фев 18, 2010 13:51:56

Сообщение Murav »

winex писал(а):поменял вектор, не 33 а 32, разрешил прерывание по UDRIE1 и вошел в прерывание
Попробуй всё таки вместо

Код: Выделить всё

#pragma interrupt_handler USART1_TX_interrupt:33
void USART1_TX_interrupt(void)
использовать конструкцию

Код: Выделить всё

ISR(USART1_TX_vect)
И кстати USART1_TX_vect объявлен как 32 вектор, а не 33, так что возможно ты напутал с нумерацией прерываний.

И в hex-файле который ты выложил таблица векторов прерываний вообще отсутствует(есть только вектор 0 - Reset и код после таблицы векторов). Так что при прошивке им контроллера, прерывания работать не будут.
Открыл глаза
Сообщения: 40
Зарегистрирован: Ср дек 09, 2009 23:05:49

Сообщение winex »

Я все-таки использовал свое обьявление прерывания. Прошил, все работает как надо.

Появился еще один вопрос, теперь по PIC.
Вот есть МК с передатчиком - rfpic12f675. Подскажите как передать байт в радиоканал? Если можно с небольшим кодом на С.
Модератор
Аватара пользователя
Сообщения: 4517
Зарегистрирован: Пн апр 03, 2006 11:43:25
Откуда: Санкт - Петербург

Сообщение Aheir »

А давайте не будем все в одну кучу валить?
Ответы на Ваши вопросы и так были на Форуме, но поискать нам лень ведь.. Создадим лучше тему еще одну. Ну а теперь до кучи навалим сюда чего-нить про ПИКи - так? )
Так что тема закрывается, а автор идет прямиков в топики по ПИКам.
Оптимизм х (Опыт + Знания) = const
Контактная информация:
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»