Страница 354 из 421

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

Добавлено: Вс фев 07, 2016 15:23:42
COKPOWEHEU
Там вроде проблема даже с прямым обращением к массиву.
Как ведет себя программа, если задать массив фиксированной длины uint8_t first[9];
Или если обращаться как к указателю
uint8_t *first = ...
*(first+5) = 1;

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

Добавлено: Вс фев 07, 2016 18:25:02
Pnjom-Penb
COKPOWEHEU писал(а):Там вроде проблема даже с прямым обращением к массиву.
Как ведет себя программа, если задать массив фиксированной длины uint8_t first[9];
Или если обращаться как к указателю
uint8_t *first = ...
*(first+5) = 1;
Вечером воскресного дня как-то не въехал - в чем проблема-то? :shock:

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

Добавлено: Вс фев 07, 2016 23:40:02
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
Я вот про эту цитату, стоит разобраться где здесь баг.

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

Добавлено: Сб фев 20, 2016 16:58:32
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.
Но тем не менее врёт...

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

Добавлено: Вс фев 21, 2016 09:53:12
Vov123
DataLife писал(а): если добавить очистку дисплея после каждого преобразования, то данные на дисплее станут более правдопадобными.
новые данные накладываются на старые

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

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

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

Как бы то ни было, всем спасибо :)

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

Добавлено: Чт фев 25, 2016 19:16:24
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--;
}
};
}

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

Добавлено: Чт фев 25, 2016 19:47:29
WiseLord
А не жалко EEPROM так насиловать?
Он, во-первых, медленный (запись вполне может не успевать в прерывании выполниться), во-вторых, ограничен в количестве циклов перезаписи. Несколько минут работы с eeprom Apos++ в прерывании - и МК можно выбрасывать на мусорку. Ну или забыть про дальнейшее использование EEPROM в нём.

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

Добавлено: Чт фев 25, 2016 20:05:45
gis
Спасибо за разъяснение. Просто я хотел чтобы он позицию помнил после выключения.

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

Добавлено: Чт фев 25, 2016 20:27:33
WiseLord
Ну так и запоминать надо при выключении, восстанавливая при включении значение.
А сотню раз в секунду флеш писать - это издевательство над МК.

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

Добавлено: Чт фев 25, 2016 21:17:49
gis
А можно сделать так чтобы контроллер понял, что его выключают. Или придется делать кнопку, по которой он будет копировал переменную в еепром ?

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

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

В широко известном на форуме проекте часов подобное реализовано.

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

Добавлено: Сб мар 05, 2016 16:58:48
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) как-раз не занята и её-то я и использую для прерываний...

Помогите, будьте добры...

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

Добавлено: Сб мар 05, 2016 17:07:50
WiseLord
Для начала я бы сделал эту переменную volatile, коль скоро она в прерывании меняется.

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

Добавлено: Сб мар 05, 2016 17:57:05
DataLife
Большое спасибо за подсказку, исправил :)
В принципе, проблему решил, всё работает. :beer:
Сделал подтяжку резистором на землю к ИНТ1, про неё я тоже забыл :)

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

Добавлено: Сб мар 05, 2016 22:33:45
alex-wolf
Здравствуйте
кто сможет помочь
sba23-11xxx.c
(12.74 КБ) 295 скачиваний
есть таблица для графо-генератора, и есть функция которая вызывается в момент запроса символа на индикатор
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);

};

};

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

Добавлено: Вс мар 06, 2016 21:19:28
DataLife
Товарищи, выручайте!

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

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

Делал так:

while (1) {

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

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

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

Но!

Имитирую шунт подстроечником. Выставляю значения АЦП ниже заданного. Условие цикла "верно". ШИМ растёт, вижу (светодиод подцепил). Как только достигло максимального значения таки выходит из цикла и дальше выводит всё на экран. Но вот потом... Потом МК снова заходит в цикл, сбрасывает OCR2 :evil: в ноль и набирает снова до максимума и выходит из цикла.
Собственно вопрос:
1. Почему OCR2 сбрасывается?
2. Как это исправить?

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

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

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

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

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

Добавлено: Вс мар 06, 2016 21:34:52
DataLife
ARV, ну просто от души спасибо! Пол дня решаю эту "загадку"!
Я-то думал, что если максимальное значение 256 есть, то добавив 1 мы его и не увеличим и не сбросим. А тут во как...
Ещё раз спасибо!

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

Добавлено: Вс мар 06, 2016 21:57:53
WiseLord
Максимальное значение восьмибитного (unsigned) числа не 256, а 255. Если добавить 1, будет 256, а это единица (она "выпадает" из восьми бит) и 8 нулей, что равносильно 0.