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

Обсуждаем контроллеры компании Atmel.
Ответить
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 302
Зарегистрирован: Пн янв 07, 2008 16:56:28
Откуда: Минск

Сообщение levaclaus »

*Trigger* писал(а):P.S. Я полностью переработал в своё время библиотеку DS18B20, тоже была нехватка памяти. Ниже моя версия.
Использовал Ваш код, получилось 80,7%. Все ли верно? Инициализацию можно выкинуть наверное, ds18b20 по умолчанию включается как 12 бит

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

#include <my_ds18b20.h>
// temp. conversion time [ms] depending on the resolution
static flash int conv_delay[4]={100,200,400,800};
// valid temp. bit mask depending on the resolution
static flash unsigned bit_mask[4]={0xFFF8,0xFFFC,0xFFFE,0xFFFF};
signed int my_ds18b20_temperature()
{
unsigned char resolution;
//if (ds18b20_read_spd(addr)==0) return -9999;
resolution=(__ds18b20_scratch_pad.conf_register>>5) & 3;
//if (ds18b20_select(addr)==0) return -9999;
w1_write(0x44);
delay_ms(conv_delay[resolution]);
//if (ds18b20_read_spd(addr)==0) return -9999;
w1_init();
return ((*((int *) &__ds18b20_scratch_pad.temp_lsb) & ((int) bit_mask[resolution]))*5/8);
}

int temp=0;

    void tem(void)
    {
    temp=my_ds18b20_temperature();    // Чтение температуры 
     if (temp>=0) {d1=12;  //пусто           
     };

     if (temp<0) { temp=-temp; d1=10; //минус
     };
          
     d2=temp/10;
     d3=temp%10;            
    }
       
    void main(void)
    {   
    
    w1_init(); 
    // ds18b20_simple_init(4);
 

    while (1)
      {   
             
           tem();
       
 
       

      }
  }
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3059
Зарегистрирован: Пн май 11, 2009 14:15:00
Откуда: СПб

Сообщение *Trigger* »

При использовании всей библиотеки не нужно объявлять отдельно my_ds18b20_temperature(), вместо этого используется ds18b20_temperature() из библиотеки. Там код ещё меньше при определённом ONE_DS18b20.
Посмотрел даташит - да, для 12 бит инициализацию можно не использовать. Библиотека-то универсальная - иногда инициализация может потребоваться.

Вот такой код получается:

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

#include <my_ds18b20.h>

int temp=0;

    void tem(void)
    {
    temp=ds18b20_temperature();    // Чтение температуры 
     if (temp>=0) {d1=12;  //пусто           
     };

     if (temp<0) { temp=-temp; d1=10; //минус
     };
          
     d2=temp/10;
     d3=temp%10;            
    }
       
    void main(void)
    {   
    
    w1_init(); 
 
    while (1)
      {               
           tem();
      }
  } 
Этот пост оказался полезен? Не поленись, нажми Изображение слева!
:) :)) :)))
Куплю индикаторы ИТС-1А, ИТС-1Б, ИГВ1-8х5Л, ИГПС1-222/7, ИГПС1-111/7 и подобные.
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 302
Зарегистрирован: Пн янв 07, 2008 16:56:28
Откуда: Минск

Сообщение levaclaus »

Если я использую стандартную функцию то не хватает места.
На данный момент пытаюсь использовать вашу библиотеку и ваш код.

В Globally #define написана строчка ONE_DS18b20
и далее

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


#include <my_ds18b20.h>


signed int my_ds18b20_temperature()
{
w1_write(0x44);
delay_ms(800);
w1_init();
return ((*((int *) &__ds18b20_scratch_pad.temp_lsb) & ((int) 0xFFFF))*5/8);
}

***

temp=my_ds18b20_temperature();

и что-то все по нулям
Друг Кота
Аватара пользователя
Сообщения: 3059
Зарегистрирован: Пн май 11, 2009 14:15:00
Откуда: СПб

Сообщение *Trigger* »

:facepalm:
Не нужно при использовании моей переделанной библиотеки объявлять заново функцию my_ds18b20_temperature(), тем более неправильно (как у Вас). В моей библиотеке есть функция ds18b20_temperature(), которая при определённом ONE_DS18b20 занимает меньше места, чем стандартная (из ds18b20.lib). Называется она также, как и в стандартной библиотеке, но использовать нужно её. Библиотеку ds18b20.lib (.h) не подключать. Нужна только my_ds1820.lib (.h).
Этот пост оказался полезен? Не поленись, нажми Изображение слева!
:) :)) :)))
Куплю индикаторы ИТС-1А, ИТС-1Б, ИГВ1-8х5Л, ИГПС1-222/7, ИГПС1-111/7 и подобные.
Реклама
Эиком - электронные компоненты и радиодетали
Прорезались зубы
Сообщения: 218
Зарегистрирован: Ср дек 02, 2015 15:06:01

Сообщение BEST-83154 »

CodeVisionAVR 3,29 есть взломанная?
Реклама
Родился
Сообщения: 11
Зарегистрирован: Вс окт 30, 2016 21:33:31

Сообщение https »

С наступившим уважаемые.
Вопрос простой.
Есть такой таймер
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{

time++;

if (time==488) {#asm("wdr");time=0;seconds++;}
if (seconds==60) {seconds=0; minutes++; }
if (minutes==60) {minutes=0; hours++; }

if( minutes==60)
{
putchar('1 hours last');
}


Хочу чтобы каждый час в uart выкидывало строчку, при такой постановке кода строки дублируется очень много раз, как сделать чтобы выкидывало 1 строчку и все, прошу прощения за мою некомпетентность в таймерах.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

А причём тут некомпетентность в таймерах? Тут просто логика неправильная.

Последний участок кода (if( minutes==60)) никак не связан с предыдущими. Поэтому выводиться это будет в любом прерывании, где minutes равно 60 - независимо от секунд и часов.

Используйте вложенные условия.
Контактная информация:
Опытный кот
Сообщения: 804
Зарегистрирован: Чт мар 12, 2009 16:31:05

Сообщение Vov123 »

Вообще логичны ли часы где есть 60 сек, 60 мин, 24 часа ? :)))
Родился
Сообщения: 11
Зарегистрирован: Вс окт 30, 2016 21:33:31

Сообщение https »

ВОт так
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{

time++;

if (time==488) {#asm("wdr");time=0;seconds++;}
if (seconds==60) {seconds=0; minutes++; }
if (minutes==60) {minutes=0; hours++; putchar('1 Hours'); }

???
Опытный кот
Сообщения: 804
Зарегистрирован: Чт мар 12, 2009 16:31:05

Сообщение Vov123 »

Ты, вообще, чужие сообщения читаешь или только свои? :shock:

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

static volatile b = флаг hours; 

if (time>487) {#asm("wdr");time=0;seconds++;}
if (seconds>59) {seconds=0; minutes++; }
if (minutes>59) {minutes=0; hours++;}

if(hours!=b){
putchar('1 Hours');
b = hours;
}

Упростил :lol:
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Добавлю: Вывод в UART обязательно делать не в этом прерывании, а в основном коде. Тупо потому, что он, весьма вероятно, занимает больше времени, проходит между прерываниями.
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 302
Зарегистрирован: Пн янв 07, 2008 16:56:28
Откуда: Минск

Сообщение levaclaus »

Коты, как красивее можно это написать?

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

     d2=temp/1000;
     d3=(temp-(1000*d2))/100;  
     d4=(temp-((100*d3)+(1000*d2)))/10;
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18679
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

d4 = (temp /= 10) % 10;
d3 = (temp /= 10) % 10;
d2 = (temp /= 10) % 10;
достаточно красиво?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 302
Зарегистрирован: Пн янв 07, 2008 16:56:28
Откуда: Минск

Сообщение levaclaus »

ARV писал(а):

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

d4 = (temp /= 10) % 10;
d3 = (temp /= 10) % 10;
d2 = (temp /= 10) % 10;
достаточно красиво?

Да, отлично, спасибо. В d4 десятки, d3 сотни, d2 тысячи ?
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18679
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

levaclaus писал(а):В d4 десятки, d3 сотни, d2 тысячи ?
как у вас было, так и осталось.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

Сообщение WiseLord »

Плюс обычно такое зацикливают. Вместо нескольких переменных - один массив:

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

uint8_t d[4];
for (i = 0; i < 4; i++) {
  d[i] = temp % 10;
  temp /= 10;
}
В итоге в массиве d[4] лежит temp поразрядно - в нулевом разряде - единицы (10⁰), в первом - десятки (10¹), во втором - сотни (10²), в третьем - тысячи (10³).

Ну и компилятор неплохо оптимизирует сочетание %10 и /10.
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 129
Зарегистрирован: Вт сен 23, 2008 14:29:06
Откуда: Ukraine

Сообщение roma1984 »

Здраствуйте! Прошу опять помощи, мучаюсь с этим спящим режимом в attiny 44, точнее пробуждением с него при помощи вачдога или другим методом.
Программа должна сделать замер напряжения, проверить все ли в норме и уснуть, потом через секунду проснутся и так по кругу.
Никак просто не пойму как это сделать, работает пока так - завел вачдог и по нему делаю ресет каждую секунду.
Код
Спойлер#include <tiny44.h>
#include <delay.h>
#define ADC_VREF_TYPE 0x00
#define charge_on PORTB.1=1;//включить пин заряда
#define charge_off PORTB.1=0;//отключить пин заряда
#define discharge_on PORTB.0=1;//включить пин разряда
#define discharge_off PORTB.0=0;//отключить пин разряда


unsigned int read_adc(unsigned char adc_input) // функция замера напряжения
{
ADMUX=(adc_input & 0x3f) | ADC_VREF_TYPE;
delay_us(10); // задержка для стабилизации напряжения
ADCSRA|=0x40; // включаєм АЦП
while ((ADCSRA & 0x10)==0); // Ждем завершения работи АЦП
ADCSRA|=0x10;
return ADCW;
}
// глобальниє переменнниє
unsigned short int Upin1, Upin2, Upin3, Upin4, Ipin, U1, U2 ,U3, U4;
float U1_Corr,U2_Corr,U3_Corr,U4_Corr;

void main(void)
{
// локальниє переменниє
Upin1=0; Upin2=0; Upin3=0; Upin4=0; Ipin=0; U1=0; U2=0; U3=0; U4=0;


// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization Func3=In Func2=Out Func1=Out Func0=Out State3=T State2=0 State1=0 State0=0
PORTB=0x03;
DDRB=0x07;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;
DIDR0=0x00;

// ADC initialization, ADC Clock: 125,000 kHz ,ADC Bipolar Input Mode: Off, ADC Auto Trigger Source: ADC Stopped
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On, ADC4: On, ADC5: On, ADC6: On, ADC7: On
DIDR0=0x00;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x83;
ADCSRB&=0x6F;

// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/128k 1 секунда
// Watchdog Timer interrupt: Off
#pragma optsize-
#asm("wdr")
WDTCSR=0x1E;
WDTCSR=0x0E;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

while (1)
{
Upin1=read_adc(0);
Upin2=read_adc(1);
Upin3=read_adc(2);
Upin4=read_adc(3);
Ipin=read_adc(4);

//вычисляем напряжение на аккумуляторах
U1=Upin1*1.5*0.0048876*1000; // 1/(20/30)* 5/1023
U2=Upin2*3.35*0.0048876*1000;// 1/(20/67) * 5/1023
U3=Upin3*4.75*0.0048876*1000; // 1/(20/95) * 5/1023
U4=Upin4*7*0.0048876*1000; // 1/(20/140) * 5/1023

U1_Corr=0; //КАЛИБРОВОЧНЫЕ ЗНАЧЕНИЯ
U2_Corr=0; //ВЫЧИТАЮТСЯ ИЗ РЕЗУЛЬТАТОВ ИЗМЕРЕНИЯ
U3_Corr=0; //ПРИ ИСПОЛЬЗОВАНИИ 0.1% РЕЗИСТОРОМ МОЖНО ОСТАВИТЬ
U4_Corr=0; //РАВНЫМИ 0

//ВЫЧИСЛЕНИЕ НАПРЯЖЕНИЙ КАЖДОЙ ЯЧЕЙКИ:
//U4=U4-U3
if (U4>U3)
{
U4=U4-U3;
if (U4>U4_Corr)
U4=U4-U4_Corr;
}
else
U4=0;

//U3=U3-U2
if (U3>U2)
{
U3=U3-U2;
if (U3>U3_Corr)
U3=U3-U3_Corr;
}
else
U3=0;

//U2=U2-U1
if (U2>U1)
{
U2=U2-U1;
if (U2>U2_Corr)
U2=U2-U2_Corr;
}
else
U2=0;

if (U1>U1_Corr)
U1=U1-U1_Corr;
else
U1=0;

//защита от переразряда
if ((U1<3000)||(U2<3000)||(U3<3000)||(U4<3000))
{
discharge_off;
}
else
{
discharge_on;
}
//защита от перезаряда
if ((U1>4200)||(U2>4200)||(U3>4200)||(U4>4200))
{
charge_off;
}
if ((U1<4150)&&(U2<4150)&&(U3<4150)&&(U4<4150))
{
charge_on;
}
//защита от КЗ
// if (Ipin>4)
// {
// discharge_off;
// charge_off;
// }

MCUCR=0x30; // разрешаєм спящий режим, Power down
#asm("sleep") // засипаем
}
}
Пробовал настраивать вачдог не на ресет, а на прерывания по срабатыванию, но ничего не вышло.
Добавлял строку
// Watchdog timeout interrupt service routine
interrupt [WDT] void wdt_timeout_isr(void)
{
// Place your code here
}

И настройки вачдога с разрешениєм прериваний:
// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/128k
// Watchdog Timer interrupt: On
#pragma optsize-
#asm("wdr")
WDTCSR=0x1E;
WDTCSR=0x4E;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Global enable interrupts
#asm("sei")

Как правильно реализовать? А то реально замучался пробовать медом тика! Спасибо!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2560
Зарегистрирован: Ср янв 16, 2008 08:34:04
Откуда: KMV

Сообщение serg_svd »

Сильно не закидывайте помидорами :)
Я присоединяюсь к теме. Решил завязать с баскомом и все же учить СИ. Выбрал кодевижен из-за более простого старта и наличия библиотек для периферии.
Из книг есть:
1. Стефан Кочан "Программирование на языке С";
2. В.В. Подбельский ""Программирование на языке С";
3. Ю. А Шпак. "Программирование на языке С для AVR и PIC микроконтроллеров"
.... ну и интернет, конечно.

Что-то получается, а что-то мой мозг вообще не хочет воспринимать и понимать в этом "странном" (после Бэйсика) для меня языке.

Скачал с официального сайта ограниченную версию 3,29. Для тренировки и обучения пока хватит и ее.

Теперь самое интересное. Написал код, который, используя встроенную библиотеку для работы с ЖК индикатором, выводит текст. Вроде проблем не возникло, пока.... пока не захотел подсчитать число символов и вывести. Вот код, я урезал лишнее и оставил лишь то, что у меня не получилось реализовать.
Спойлер

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

#include <io.h>
#include <iobits.h>
#include <string.h>
#include <alcd.h>
#include <stdio.h>


char text2[10]="Test";
char i;

,,,,,,


    lcd_init(16);               // Инициализация дисплея в 16 символов в строке
    lcd_clear();                // Очистка дисплея
    lcd_gotoxy(0,0); 
    i=strlen(text2);
    lcd_puts(i);



И получаю в строке lcd_puts(i); ошибку несоответствия типов переменных Error: function argument #1 of type 'unsigned char' is incompatible with required parameter of type 'unsigned char *'

Объясните чайнику, пожалуйста, отчего она возникла? Как правильно все же должен выглядеть этот кусок кода?

Насчет литературы, может подскажете еще обучалку для чайника? Только просьба на сайт 123 не отправлять.

Добавлено after 6 minutes 7 seconds:
Кстати вдогонку еще один тупой вопрос задам.
Есть строковая переменная, допустим, состоящая из 25 символов. Эти 25 символов составляют некое предложение из N слов. Если я вывожу эту переменную на ЖК индикатор 16х2, то, заполнив первую строку 16 символами, текст перейдет на вторую строчку. При этом одно слово будет разбито на 2 строки.
Подскажите, как нужно написать код, чтобы слово не разбивалось, а переносилось на другую строчку целиком? Как я понимаю, готовой функции нет в кодевижен для этого и нужно писать свой код. Правильно?
"Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа." Ро́берт Ше́кли
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Не знаю CodeVision, но полагаю, что функция lcd_puts() по смыслу должна принимать в качестве аргумента строку (или указатель на char, что то же самое по сути), а Вы пытаетесь ей целое число скормить зачем-то.
заполнив первую строку 16 символами, текст перейдет на вторую строчку
Вовсе нет.
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2560
Зарегистрирован: Ср янв 16, 2008 08:34:04
Откуда: KMV

Сообщение serg_svd »

WiseLord писал(а): функция lcd_puts() по смыслу должна принимать в качестве аргумента строку
Почему тогда в примерах к этой программе через нее выводят и числа? Я в этой библиотеке для ЖК индикатора не видел других функций именно для чисел. И меня смущает наличие в строчке ошибки знака указателя (*).
Помощь к программе есть, и здоровенный файл хэлпа. Но они рассчитаны на людей уже владеющих С. А с нуля по ним учиться очень трудно. Потому, что в них (да и в моих книжках тоже) почему-то не описаны фундаментальные основы языка. Надо искать преподавателя, что-то мне так кажется.
WiseLord писал(а):Вовсе нет.
Что в баскоме, что сейчас у меня в попытках обучения С, при выводе информации на жк строка переносится автоматически. Я параллельно смотрю симуляцию в протеус.

А я и заинтересовался, как можно длинную строковый массив разбить по словам самому, потому, что это пригодится мне в моем проекте.
"Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа." Ро́берт Ше́кли
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Ответить

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