CodeVision AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: CodeVision AVR в вопросах и ответах

Сообщение COKPOWEHEU »

Там вроде проблема даже с прямым обращением к массиву.
Как ведет себя программа, если задать массив фиксированной длины uint8_t first[9];
Или если обращаться как к указателю
uint8_t *first = ...
*(first+5) = 1;
Реклама
Pnjom-Penb
Мучитель микросхем
Сообщения: 469
Зарегистрирован: Вс авг 30, 2015 03:52:59

Re: CodeVision AVR в вопросах и ответах

Сообщение Pnjom-Penb »

COKPOWEHEU писал(а):Там вроде проблема даже с прямым обращением к массиву.
Как ведет себя программа, если задать массив фиксированной длины uint8_t first[9];
Или если обращаться как к указателю
uint8_t *first = ...
*(first+5) = 1;
Вечером воскресного дня как-то не въехал - в чем проблема-то? :shock:
Реклама
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: CodeVision AVR в вопросах и ответах

Сообщение COKPOWEHEU »

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

D2printf("first = ");
    for(i=0;i<9;i++)   
    {     
        first[i] = i;
        D2printf("%u ", first[i]);
    }   
    D2printf("\n");
Даже такая простая операция выдаёт: first = 0 1 2 3 0 0 0 0 0
Я вот про эту цитату, стоит разобраться где здесь баг.
Аватара пользователя
DataLife
Вымогатель припоя
Сообщения: 601
Зарегистрирован: Пт фев 13, 2009 20:58:13
Откуда: Донецк

Re: CodeVision AVR в вопросах и ответах

Сообщение DataLife »

Доброго времени суток.
Где-то закрался косяк с скромный код программы-вольтметра (вернее измерителя АЦП) с выводом значения на LCD 16x2 экранчик.

Отдельно измеритель код АЦП работает, что показывает не одно моё устройство.
Отдельно вывод динамических данных на дисплей тоже работает. Проверил...
Всё это вместе работает более чем странно:
Значения АЦП должны быть 0...1024, но независимо от того, на GND или на Vcc я подкину ногу ADC0, на экране данные от 100 до 9800 (примерно) :shock: И скачут как им хочется.

МК ATmega8A.

Может кто ткнёт носом в ошибку?
Спойлер/****************
AVR Core Clock frequency: 1,000000 MHz
*****************/

#include <mega8.h>
#include <lcd.h>
#include <delay.h>
#include <stdio.h> // библиотека для преобразования переменных в строки

#asm
.equ __lcd_port=0x12; PORTD /* ЖКИ дисплей подключили к порту I/O D */
#endasm

// Обьявзяем переменные
char lcd_buffer[20]; // создается буфер (масив) для символов, выводимых на дисплей
unsigned int res; // переменная для хранения хначения АЦП

//Функция измерения АЦП

unsigned int ADC_result(void)
{
ADCSRA = 0b10000100; // - предделитель на 16, прерывания запрещены, ADC включён
ADMUX = 0b11000000; // - 2.56VCC , ACD0, ADLAR off
delay_us(30); //задержка для стабилизации
ADCSRA |= 0x40; //начинаем измерение
while((ADCSRA & 0x10)==0); //Ждём флаг окончания измерения
ADCSRA |=0x10;
return ADCW; //Возвращаем функции значение регистра ADCW
}

void main(void) /* Основная функция "main", с которой начинается выполнение всей программой процедуры */
{

lcd_init(16);
lcd_gotoxy(2,0);
lcd_putsf("Digital ADC");
lcd_gotoxy(1,1);
lcd_putsf("CodeVision AVR");
delay_ms(1000);
lcd_clear();

while(1){
res = ADC_result(); //значение измерения АЦП присваеваем переменной RES
lcd_gotoxy(0,0);
sprintf(lcd_buffer, "ADC = %i", res); // преобразуем переменные в строки
lcd_puts(lcd_buffer); // выводим строку на дисплей
delay_ms(500);
lcd_clear(); // первая ошибка
}
}
UPD1: если добавить очистку дисплея после каждого преобразования, то данные на дисплее станут более правдопадобными. При подключении на "землю" показывает 105...90, а при подключении на +5 показывает ~900.
Но тем не менее врёт...
Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного.
Реклама
Эиком - электронные компоненты и радиодетали
Vov123
Опытный кот
Сообщения: 804
Зарегистрирован: Чт мар 12, 2009 16:31:05

Re: CodeVision AVR в вопросах и ответах

Сообщение Vov123 »

DataLife писал(а): если добавить очистку дисплея после каждого преобразования, то данные на дисплее станут более правдопадобными.
новые данные накладываются на старые
Реклама
Аватара пользователя
DataLife
Вымогатель припоя
Сообщения: 601
Зарегистрирован: Пт фев 13, 2009 20:58:13
Откуда: Донецк

Re: CodeVision AVR в вопросах и ответах

Сообщение DataLife »

Вопрос решил.
Ещё всё досконально проверю, но вышло так: скорее всего нужно было подтянуть AREF на землю через конденсатор. На моей версии плате это я не предусмотрел, зато предусмотрел LC фильтр для AVCC. Перенастроил АЦП на эту ногу, а не на внутренние 2.56В, и всё стало показывать верно.

Учиться... учиться ... и ещё раз учиться :)

Как бы то ни было, всем спасибо :)
Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного.
Реклама
gis
Родился
Сообщения: 16
Зарегистрирован: Пт ноя 07, 2014 20:34:56

Re: CodeVision AVR в вопросах и ответах

Сообщение gis »

Здравствуйте, у меня следующая проблема. С ATmega8 мне необходимо управлять драйвером шаговика по step/dir. Кусок кода ниже работает, но если заявить переменную Apos в eeprom, то ничего не работает (драйвер включает обмотки хаотично, LCD- экранчик не инициализируется). Кажется, что контроллер не стартует. Не могу понять как это может быть связано с тем, для какой памяти я заявляю переменную.

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

eeprom int Zpos= 10000;    //заданное положение
int Apos=0;                       //актуальное положение

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0x83;
if (Apos==Zpos)
{MOTOR_ENABLE=0;}
else
{
if (Apos<Zpos)
{
MOTOR_DIRECTION=1;
MOTOR_ENABLE=1;
MOTOR_STEP=1;
delay_us(5) ;
MOTOR_STEP=0;
Apos++;
}
else
{
MOTOR_DIRECTION=0;
MOTOR_ENABLE=1;
MOTOR_STEP=1;
delay_us(5) ;
MOTOR_STEP=0;
Apos--;
}
};
}
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение WiseLord »

А не жалко EEPROM так насиловать?
Он, во-первых, медленный (запись вполне может не успевать в прерывании выполниться), во-вторых, ограничен в количестве циклов перезаписи. Несколько минут работы с eeprom Apos++ в прерывании - и МК можно выбрасывать на мусорку. Ну или забыть про дальнейшее использование EEPROM в нём.
gis
Родился
Сообщения: 16
Зарегистрирован: Пт ноя 07, 2014 20:34:56

Re: CodeVision AVR в вопросах и ответах

Сообщение gis »

Спасибо за разъяснение. Просто я хотел чтобы он позицию помнил после выключения.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение WiseLord »

Ну так и запоминать надо при выключении, восстанавливая при включении значение.
А сотню раз в секунду флеш писать - это издевательство над МК.
gis
Родился
Сообщения: 16
Зарегистрирован: Пт ноя 07, 2014 20:34:56

Re: CodeVision AVR в вопросах и ответах

Сообщение gis »

А можно сделать так чтобы контроллер понял, что его выключают. Или придется делать кнопку, по которой он будет копировал переменную в еепром ?
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение WiseLord »

Проще кнопкой. Но можно и с помощью АЦП или входа INT0/1. Главное, чтобы питание МК снижалось медленнее (за счёт тех же конденсаторов по питанию) чем напряжение на входе АЦП или уровень на INT0/1 (резистивный делитель, отделённый диодом от основного питания). Тогда можно отловить факт отключения и сохранить в EEPROM значение ещё до того, как питание МК окончательно пропадёт.

В широко известном на форуме проекте часов подобное реализовано.
Аватара пользователя
DataLife
Вымогатель припоя
Сообщения: 601
Зарегистрирован: Пт фев 13, 2009 20:58:13
Откуда: Донецк

Re: CodeVision AVR в вопросах и ответах

Сообщение DataLife »

Доброго времени суток, коты!
Не могу разобраться в, казалось бы, простых вещах.

МК: ATmega8

Суть: нужно сидеть в цикле while до тех пор, пока некая переменная не поменяет своё значение с 0 на 1.
Сама переменная изменяет своё значение в результате внешнего прерывания по INT1.

У меня же этот цикл пролетает, не дожидаясь изменения переменной, а далее, когда нужно зайти в цикл при условии "переменная == 1" он не заходит.

Может криво объяснил, но вот часть программы:
Спойлерunsigned char start = 0;


interrupt [EXT_INT1] void ext_int1_isr(void) // обработчик прерывания от кнопки СТАРТ
{
start++;
if (start == 2)
{start = 0;}
}

void main(void)
{

#asm("sei") // глобально разрешаем прерывания

GICR|=0x80; // разрешаем прерывание по INT1
MCUCR=0x08; // прерывание по спадающему фронту сигнала на INT1
GIFR=0x80;

while (start == 0) // пока не нажали кнопку пуска...
{
// делаем что-то, ПОКА переменная старт = 0
}

/*** ещё часть программы ***/


while (start == 1)

{
// делаем что-то, ПОКА переменная старт = 1
}
}
То есть цикл while (start == 0) у меня выполняется один раз, а в цикл while (start == 1) вообще не заходит...

Есть подозрения, что виной тому LCD 16x2, что подключён к порту D. Но нога с INT1 (PD3) как-раз не занята и её-то я и использую для прерываний...

Помогите, будьте добры...
Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение WiseLord »

Для начала я бы сделал эту переменную volatile, коль скоро она в прерывании меняется.
Аватара пользователя
DataLife
Вымогатель припоя
Сообщения: 601
Зарегистрирован: Пт фев 13, 2009 20:58:13
Откуда: Донецк

Re: CodeVision AVR в вопросах и ответах

Сообщение DataLife »

Большое спасибо за подсказку, исправил :)
В принципе, проблему решил, всё работает. :beer:
Сделал подтяжку резистором на землю к ИНТ1, про неё я тоже забыл :)
Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного.
Аватара пользователя
alex-wolf
Открыл глаза
Сообщения: 63
Зарегистрирован: Сб мар 09, 2013 21:46:01
Откуда: Уфа
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение alex-wolf »

Здравствуйте
кто сможет помочь
sba23-11xxx.c
(12.74 КБ) 292 скачивания
есть таблица для графо-генератора, и есть функция которая вызывается в момент запроса символа на индикатор
http://yandex.ru/clck/jsredir?from=yand ... 1926211216

есть немого лишнего, к каждому разряду -цвета нужно указывать таблицу, а это съедает память (еще нужно запихнуть для atmega8 еще и протокол mod_bus с фиксированным адресом , и читать указанные регистры, и исходя из значений выводить число, норма =зеленый, повышенный =оранжевый , критично = красный)

Изображение
Изображение

в конкретном примере значение числа производилось из чтение регистра секунд ds1307
Изображение
Изображение
Изображение


кусочек кода для оценки что получилось


pwm_=2;
//delay_ms(1000);
red_x10=red_x1='_'; green_x10='S';green_x1='T';green_x1='.';
delay_ms(1000);
pwm_=3;
BlkScrAll(); pwm_=1;
while (1) {
read_date_time(&sec,&minut,&hour,&day,&date,&month,&year);
ds1307_rddata=bcd2bin(ds1307_read(0x0));
//*
//используются для сравнения переменных, чисел (констант) и выражений.
//x < y // X меньше Y
//x > y // больше
//x <= y // меньше или равно
//x >= y // больше или равно
//x == y // равно
//x != y /* не равно
//| | // "ИЛИ" - только "ложь" и "ложь"
// дают "ложь"
//&& // "И" - только "истина" и "истина"
// дают "истина"
//! "НЕ" - логическое отрицание

//////////////////////////////////////////
// green_x1=((rc5_command));
// green_x10=((rc5_device));
//// green_x1=((rc5_command)10);
//// green_x10=((rc5_device)10);
////number_r(rc5_adr_out);
//green_x10_dp=(rc5_trg_out); red_x1_dp=(RC5_buffer [0]); green_x1_dp=(RC5_buffer [1]);
// BlkScrAll();

//

if((ds1307_rddata)<50) {
// green_x1=((ds1307_rddata)%10);
// green_x10=((ds1307_rddata)/10);
number_g(ds1307_rddata);
if ((ds1307_rddata) & (0x01) ) {green_x1_dp=(1);}
else {green_x1_dp=(0);};
}
else {
// red_x1=((ds1307_rddata)%10);
// red_x10=((ds1307_rddata)/10);
if ((ds1307_rddata) & (0x01) ) {green_x1_dp=(1);}
else {green_x1_dp=(0);};

number_r(ds1307_rddata);
}
if((ds1307_rddata)>44) {

// red_x1=((ds1307_rddata)%10);
// red_x10=((ds1307_rddata)/10);
// green_x1=((ds1307_rddata)%10);
// green_x10=((ds1307_rddata)/10);
number_y(ds1307_rddata);

if ((ds1307_rddata) & (0x01) ) {green_x1_dp=(1);}
else {green_x1_dp=(0);};

};

if((ds1307_rddata)>54) {

// BlkScrAll();
// red_x1=((ds1307_rddata)%10);
// red_x10=((ds1307_rddata)/10);
number_r(ds1307_rddata);
if ((ds1307_rddata) & (0x01) ) {green_x1_dp=(1);}
else {green_x1_dp=(0);}; };



if ((ds1307_rddata)==03 || PIND.2 == 0){;BlkScrAll();delay_ms(500);green_x10=(21);delay_ms(500);BlkScrAll();delay_ms(500);
green_x1=(((bcd2bin(ds1307_read(0x2))))%10);red_x1_dp=(1); green_x10=(((bcd2bin(ds1307_read(0x2))))/10);
delay_ms(1000);BlkScrAll();

BlkScrAll();delay_ms(500);number_g(bcd2bin(ds1307_read(0x1)));delay_ms(1000);BlkScrAll(); }

//// green_x1=red_x1=((bcd2bin(ds1307_read(0x0)))%10);
//red_x10=green_x10=((bcd2bin(ds1307_read(0x0)))/10);


delay_ms(1);

};

};
Аватара пользователя
DataLife
Вымогатель припоя
Сообщения: 601
Зарегистрирован: Пт фев 13, 2009 20:58:13
Откуда: Донецк

Re: CodeVision AVR в вопросах и ответах

Сообщение DataLife »

Товарищи, выручайте!

Не могу корректно выполнить поставленную задачу.
Делаю некое зарядное с мозгами на мега8.

Нужно мне увеличивать ШИМ, если напряжение на шунте (ток) ниже заданного.

Делал так:

while (1) {

while (ADC_shunt() <= ("условие"))
{
OCR2=OCR2+0x01;
if (OCR2==0xFF) break;
}

/** вывод разного на экран ***/
}

Дальше идёт вывод всего на дисплей, то не важно.
Казалось бы всё просто и верно: пока условие "напряжение меньше чем должно быть" - увеличиваем OCR2. Соответственно вырос реальный ток - выросло напряжение на шунте и тд. Если OCR2 достигло своего максимального значения, а условие не выполнено - выходим из цикла. Ну проще некуда!

Но!

Имитирую шунт подстроечником. Выставляю значения АЦП ниже заданного. Условие цикла "верно". ШИМ растёт, вижу (светодиод подцепил). Как только достигло максимального значения таки выходит из цикла и дальше выводит всё на экран. Но вот потом... Потом МК снова заходит в цикл, сбрасывает OCR2 :evil: в ноль и набирает снова до максимума и выходит из цикла.
Собственно вопрос:
1. Почему OCR2 сбрасывается?
2. Как это исправить?
Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение ARV »

DataLife писал(а):1. Почему OCR2 сбрасывается?
ну так вы закончили цикл в момент, когда OCR2==0xFF, а потом входите в цикл снова и увеличиваете OCR2 на 1. что будет если к байту 0xFF прибавить 1? байт станет равным 0.
DataLife писал(а):2. Как это исправить?
элементарно:

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

while (ADC_shunt() <= ("условие"))
{
if (OCR2==0xFF) break;
OCR2=OCR2+0x01;
}
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
DataLife
Вымогатель припоя
Сообщения: 601
Зарегистрирован: Пт фев 13, 2009 20:58:13
Откуда: Донецк

Re: CodeVision AVR в вопросах и ответах

Сообщение DataLife »

ARV, ну просто от души спасибо! Пол дня решаю эту "загадку"!
Я-то думал, что если максимальное значение 256 есть, то добавив 1 мы его и не увеличим и не сбросим. А тут во как...
Ещё раз спасибо!
Только те, кто предпринимают абсурдные попытки, смогут достичь невозможного.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: CodeVision AVR в вопросах и ответах

Сообщение WiseLord »

Максимальное значение восьмибитного (unsigned) числа не 256, а 255. Если добавить 1, будет 256, а это единица (она "выпадает" из восьми бит) и 8 нулей, что равносильно 0.
Ответить

Вернуться в «AVR»