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

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

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

Сообщение serg_svd »

Продолжаю разбираться с UART. Вроде получилось выводить текст на гипертерминал, используя созданную мастером функцию getchar();.
Осталось разобраться с приемом.

Но всплыли вопросы поважнее.
1. в начале кода у меня прописана строковая константа в EEPROM, я ранее уже интересовался по ее поводу. ПримерЖ

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

unsigned eeprom char Text[16]="Test EEPROM";

Эта константа сохраняется в EEPROM, начиная с адреса 0х00. Как сделать, чтобы нулевой адрес пропускался и писалось в адрес 0х01? Для защиты от сбоя. Я в интернете в описаниях кодевижена встречал фразу, что компилятор сам сдвигает данные и не дает заполнять ячейку 0х00. Но в настройках программы я этого не увидел.

2. Вопрос чисто сишный. Область хранения переменных может быть задана RAM, FLASH, EEPROM. Соответственно при вызове функции, которой требуется передать данные на обработку, тоже прописывается тип данных.
У меня сейчас получилось так, что есть данные во всех трех областях памяти, а функции их обрабатывающие по внутреннему коду идентичны. Отличие как раз в определении переменной в функции. Можно ли написать одну функцию, а вызывать ее с данными, хранящимися в RAM, FLASH, EEPROM вместо трех?
"Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа." Ро́берт Ше́кли
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

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

Сообщение pyzhman »

1.

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

unsigned eeprom char Empty;
unsigned eeprom char Text[16]="Test EEPROM";


Добавлено after 5 minutes 38 seconds:
serg_svd писал(а):...Для защиты от сбоя...

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

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

Сообщение serg_svd »

pyzhman писал(а):

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

unsigned eeprom char Empty;
unsigned eeprom char Text[16]="Test EEPROM";


В первую очередь так пробовал. Компилятор ругается

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

Warning:  global variable 'Empty' was declared, but not referenced

И тупо ее пропускает. Запись следующей константы начинается все равно с адреса 0х00

Вы сталкивались с такими сбоями?

Да слава Богу нет еще. Да и BODLEVEL включаю, если EEPROM использую. Но вот начитался "страстей" в интернете и решил сработать на предупреждение проблем :)
"Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа." Ро́берт Ше́кли
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

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

Сообщение uk8amk »

2.
Данные хранятся в разных типах памяти и способы обращения к этим областям различаются. Если работа на уровне языка Си с этими данными идентична(или как минимум похожа), то компилятор AVR генерирует разный код.
LPM - для чтения флеш
LDS - для чтения ОЗУ
Такая задумка возможна на контроллерах с единым адресным пространством. В вашем случае придётся довольствоваться загрузкой данных в буфер ОЗУ и передачи его указателя в функцию обработки.

serg_svd писал(а):И тупо ее пропускает.

Есть волшебное слово volatile
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

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

Сообщение pyzhman »

Warning: global variable 'Empty' was declared, but not referenced

Надеюсь, поняли, что это обозначает?
Docendo discimus
Аватара пользователя
serg_svd
Собутыльник Кота
Сообщения: 2560
Зарегистрирован: Ср янв 16, 2008 08:34:04
Откуда: KMV

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

Сообщение serg_svd »

pyzhman писал(а):Надеюсь, поняли, что это обозначает?

Переменная объявлена, но не используется

uk8amk писал(а):Есть волшебное слово volatile

Попробовал, тоже не помогло.
"Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа." Ро́берт Ше́кли
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

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

Сообщение pyzhman »

Так используйте ее вхолостую хотя бы раз.

Добавлено after 1 minute 34 seconds:
serg_svd писал(а):...начитался "страстей" в интернете...

Читать нужно еррата в даташите и следовать рекомендациям производителя.
Опять же
константа в EEPROM

Смысл? Что мешает хранить ее во флеше?
Возвращаясь к ЕЕПРОМ - используйте, если уж на то пошло, 24С...
Docendo discimus
Аватара пользователя
serg_svd
Собутыльник Кота
Сообщения: 2560
Зарегистрирован: Ср янв 16, 2008 08:34:04
Откуда: KMV

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

Сообщение serg_svd »

pyzhman писал(а):Читать нужно еррата в даташите и следовать рекомендациям производителя.

Читал. Поэтому BODLEVEL и включаю.

pyzhman писал(а):если уж на то пошло, 24С...

А смысла нет. Данные будут меняться очень редко. И проще их менять не перепрошивая каждый раз контроллер и не применяя внешнюю память. Объема EEPROM хватает с головой. Общение с устройством будет через UART. Через него же и ввод новых значений с последующей записью в EEPROM.
"Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа." Ро́берт Ше́кли
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Аватара пользователя
oleg110592
Друг Кота
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

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

Сообщение oleg110592 »

serg_svd писал(а):Как сделать, чтобы нулевой адрес пропускался и писалось в адрес 0х01? Для защиты от сбоя.

лет незнаюсколько назад Атмел вроде победил порчу 0 ячейки еепром, если надо перебдеть, можно структурным способом:

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

 eeprom struct eeprom_structure
{
    unsigned char bad0E;
    unsigned char var1E;
    unsigned int var2E;
} par;

unsigned char temp;

void main(void)
{
    temp = par.var1E;
    while (1)
      {
      }
}
Аватара пользователя
AndTer
Поставщик валерьянки для Кота
Сообщения: 2406
Зарегистрирован: Ср фев 23, 2011 12:12:31

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

Сообщение AndTer »

И всё же крокодил не ловится...
Протеус при симуляции показывает что каждый период запускается по три раза... Хотя должен по одному...
Понимаю что протеусу доверять сильно не стоит, но нет ничего чем мог бы записать и посмотреть что вылазит с мк...
Изображение
И собственно код:
Спойлер/*****************************************************
AVR Core Clock frequency: 16,000000 MHz
*****************************************************/

#include <mega8.h>

// Declare your global variables here
unsigned char SND[]={0x05,0x0D};
int i=1;

// Timer1 input capture interrupt service routine
interrupt [TIM1_CAPT] void timer1_capt_isr(void)
{
OCR1AL=SND[i];
i=i-1;
if(i<0)i=1;
}

void main(void)
{
PORTB=0x00;
DDRB=0x02;
PORTC=0x00;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;
TCCR0=0x00;
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: Fast PWM top=ICR1
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: On
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x82;
TCCR1B=0x18;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x13;
OCR1AH=0x00;
OCR1AL=0x13;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x20;

// Global enable interrupts
#asm("sei")

TCCR1B=0x19;

while (1)
{
// Place your code here

};
}

На проверку переменной i в прерывании не обращайте внимания, массив последовательностей, как и она сама, будет больше чем 1 поэтому такое условие.
Глупый не задает вопросы. Глупый и так все знает.
Аватара пользователя
kadenca
Родился
Сообщения: 8
Зарегистрирован: Пн май 18, 2015 17:41:09

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

Сообщение kadenca »

Здравствуйте. Буду очень благодарен за любую помощь. Пытаюсь по UART получить заведомо известную строку и по этой строке выполнить определенное действие. Написал такой Код в CodeVision

volatile char led_ON[7]="Led_ON"; //верная строка для включения светодиода
volatile char led_OFF[7]="Led_OF";// верная строка для выключения светодиода
volatile char buff[6]; // буфер для размещения пришедших символов

while (1)
{

if(gets(buff,6)) // если пришедшие символы размещены в буфере, сравним их с заведомо известными строками
{

if ( strcmp(led_ON, buff) == 0) // если строки в массивах led_ON и buff совпадают
{ // включим светодиод
PORTB.0=1;
}

if ( strcmp(led_OFF, buff) == 0)
// если строки в массивах led_OFF и buff совпадают
{ // выключим светодиод
PORTB.0=0;
}

printf("%s",buff,"\r\n");
// выведем то что есть в буфере
}

}


вообщем как только я отсылаю по UART строку "Led_ON" светодиод загорается, отправляю "Led_OF" светодиод потухает. И так можно делать много раз и все работает.

Но стоит отправить что-то другой, например "123" и после этого команды "Led_ON" и "Led_OF" не работают (.

И по UART ф-цией printf() я получаю уже, что-то вроде _ONLed, d_ONLe... те же символы, но в разном порядке. Как с этим бороться?) Заранее большое спасибо.

P/S и еще вопрос в функции gets(buff,6) цифра 6 задает количество символов, которые необходимо записать из потока?
Аватара пользователя
AndTer
Поставщик валерьянки для Кота
Сообщения: 2406
Зарегистрирован: Ср фев 23, 2011 12:12:31

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

Сообщение AndTer »

Подскажите "красивое" решение:
Имеем число, нужно разбить его на массив:

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

unsigned long int X=256879;
int M[9];

На выходе нужно получить:

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

M[0]=2
M[1]=5
M[2]=6
M[3]=8
M[4]=7
M[5]=9
...


Сам себе отвечаю:

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

unsigned long int X=256879;
int M[9];

unsigned long int e=0;
int i=0;

e=X;
for(i=5;i>=0;i--)
{
  M[i]=e%10;
  e/=10;
}
Последний раз редактировалось AndTer Вс янв 29, 2017 11:24:47, всего редактировалось 1 раз.
Глупый не задает вопросы. Глупый и так все знает.
misterkuk
Мучитель микросхем
Сообщения: 400
Зарегистрирован: Сб апр 17, 2010 10:30:13
Контактная информация:

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

Сообщение misterkuk »

Суть программы- автомобильный термометр на 4 канала. Датчики температуры ds18b20. проц atmega8. при первм запуске с нажатой кнопкой программа входит в режим записи в еепром индивидуальных данных датчиков. после сохранения данных схема запускается с отжатой кнопкой, данные считываются из еепром в массив и далее программа работает с массивом. Всё рааботает. Но на дисплее прыгают значения показаний датчиков. Это уже не первый проэкт с такой проблемой. Допустим на экране высвечивается 25.0 градусов через время, а оно разное всегда, появляется -9999.0 потом при следующем круге программы появляется 25.09.0 тоесть нормально высвителось, но последние 9.0 остались.
было 2 5 . 0
стало - 9 9 9 9 . 0
стало 2 5 . 0 9 . 0
Я сначала думал что лишние цифры остаются в буфере массива. Попробывал чистить его перед записью- не помогло. Выходит эти цифры остаются в дисплее. Потом думал что не правильно считывается температура с датчика. Сделал проверку. Считываю температуру в переменную. Проверяю лежат ли считанные данные в пределах и потом отправляю переменную в sprintf. ошибка не пропала. Это значит что температура считывается без ошибок проходит проверку, уходит в sprintf и тут этот глюк и зараждается. А именно в строчке sprintf( LcdBuff,"motor %.1f", ds18b20_temperature( &RomCode[1][0] ) );
Подскажите, в чемм пожет быть причина? Фото прелагаются. Код программы в спойлере. Да программа корявенькая, но работает. только показания всё портят.
Спойлер

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

#include <mega8.h>
#include <delay.h>
#include <io.h>
#include <stdio.h>
#include <eeprom.h>
#include <1wire.h>
#include <ds18b20.h>
#include <alcd.h>
#define MAX_DS1820 4

 #asm
  .equ __w1_port=0x12
  .equ __w1_bit=1
#endasm

unsigned char nastroyka=0;
unsigned char RomCode[4][9];
int i;
int j;
int flag=7000;
unsigned char EEPROM_ADRESS_MASS=0x10;
unsigned char dspor=0x00;
unsigned char LcdBuff[20];
unsigned char devices;
unsigned int adc_data;
float t;



// Declare your global variables here
// Voltage Reference: Int., cap. on AREF
#define ADC_VREF_TYPE ((1<<REFS1) | (1<<REFS0) | (0<<ADLAR))
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
// Read the AD conversion result
adc_data=ADCW;
// Place your code here
}


// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
flag+=1;
}

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRC=(0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
// State: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
TCCR0=(1<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0<<AS2;
TCCR2=(0<<PWM2) | (0<<COM21) | (0<<COM20) | (0<<CTC2) | (0<<CS22) | (0<<CS21) | (0<<CS20);
TCNT2=0x00;
OCR2=0x00;


// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<TOIE0);

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);

// USART initialization
// USART disabled
UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (0<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);

// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);

// ADC initialization
// ADC Clock frequency: 125,000 kHz
// ADC Voltage Reference: Int., cap. on AREF
ADMUX=ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADFR) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
SFIOR=(0<<ACME);

// SPI initialization
// SPI disabled
SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);

// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);

// 1 Wire Bus initialization
// 1 Wire Data port: PORTD
// 1 Wire Data bit: 1
// Note: 1 Wire port settings are specified in the
// Project|Configure|C Compiler|Libraries|1 Wire menu.
w1_init();



// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTB Bit 4
// RD - PORTB Bit 3
// EN - PORTB Bit 2
// D4 - PORTB Bit 1
// D5 - PORTB Bit 0
// D6 - PORTD Bit 7
// D7 - PORTD Bit 6
// Characters/line: 8


// Global enable interrupts



if (PIND.5==0)
nastroyka=1;

w1_init();
lcd_init(20);
lcd_clear(); //очистить дисплей



     
if(nastroyka==0)
{
EEPROM_ADRESS_MASS=0x10;
  for ( i = 0; i<4; i++)
  {
    for (j = 0; j < 9; j++)
    {
    RomCode[i][j] = eeprom_read_word(EEPROM_ADRESS_MASS);
    EEPROM_ADRESS_MASS+=1;
    }
  }
}

ds18b20_init( &RomCode[0][0], -20, 125, DS18B20_9BIT_RES );
ds18b20_init( &RomCode[1][0], -20, 125, DS18B20_9BIT_RES );
ds18b20_init( &RomCode[2][0], -20, 125, DS18B20_9BIT_RES );
ds18b20_init( &RomCode[3][0], -20, 125, DS18B20_9BIT_RES );
#asm("sei")
while (1)
{
      if(nastroyka==0 )
      {                 
         lcd_gotoxy(0,0);
         sprintf( LcdBuff,"salon %.1f", ds18b20_temperature( &RomCode[0][0] ) );
         delay_us(50);
         lcd_puts(LcdBuff);     
     
         lcd_gotoxy(0,1);
         sprintf( LcdBuff,"motor %.1f", ds18b20_temperature( &RomCode[1][0] ) );
         delay_us(50);
         lcd_puts(LcdBuff);       

         lcd_gotoxy(0,2);
         sprintf( LcdBuff,"pechka %.1f", ds18b20_temperature( &RomCode[2][0] ) );
         delay_us(50);
         lcd_puts(LcdBuff);         

         lcd_gotoxy(0,3);
         sprintf( LcdBuff,"ulitsa %.1f", t );
         delay_us(50);
         lcd_puts(LcdBuff);               
        }

          if(nastroyka==1)
         {
          devices=w1_search( DS18B20_SEARCH_ROM_CMD, RomCode ); //поиск датчиков на линии 1-wire
          lcd_gotoxy(0,0);   
          sprintf(LcdBuff,"DS18B20=%u",devices); //выводим информацию о кол-ве датчиков
          lcd_puts(LcdBuff);
          delay_ms(500);
          delay_ms(500);
           lcd_clear(); //очистить дисплей
         }
            dspor=eeprom_read_word(0x00);
            if(dspor==255)
            dspor=0;   
                if(dspor<=3)
               {           
                for (j = 0; j < 9; j++)
               {
                 eeprom_write_word(EEPROM_ADRESS_MASS,RomCode[0][j]);
                 EEPROM_ADRESS_MASS+=1;
               }
             
          #asm("cli")
          dspor+=1;
          eeprom_write_word(0x00,dspor);
                       
          #asm("sei")
          lcd_gotoxy(0,0);
          lcd_putsf("okey");
          }
          while (PIND.5==0)
          {

          }

}
}


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

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

ИзображениеИзображение
Вложения
3.png
(1.39 КБ) 498 скачиваний
2.png
(1.51 КБ) 482 скачивания
1.png
(1.44 КБ) 241 скачивание
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

CRC при съёме показаний проверяется? Если данные приходят от датчика некорректные, нужно их просто игнорировать.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

во-первых, не понятно, у вас графический или символьный ЖКИ? ощущение, что символьный, и тогда причина такого нехорошего поведения очевидна: вы не очищаете строку символов дисплея до конца.
во-вторых, показания термометра 9999 и т.п. - это сигнализация об ошибке обмена с датчиком, и в этом случае выводить результат не нужно. у вас в коде анализа ошибочной ситуации нет, а должна быть.

чтобы решить первую проблему, достаточно при выводе строки всегда выводить одинаковое количество символов, равное количеству позиций в строке ЖКИ. например, если у вас в строке 16 знаков, то ввод должен быть таким:

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

#define LINE_LEN   16

void fix_str_output(char *s){
   unsigned char len;
   lcd_puts(s);
   len = LINE_LEN - strlen(s);
   for(;len; len--) lcd_putc(' ');
}


ну а борьбу со второй проблемой сделайте самостоятельно.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
AndTer
Поставщик валерьянки для Кота
Сообщения: 2406
Зарегистрирован: Ср фев 23, 2011 12:12:31

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

Сообщение AndTer »

Как можно осуществить сброс МК программно?
Глупый не задает вопросы. Глупый и так все знает.
rusl32
Родился
Сообщения: 17
Зарегистрирован: Вс окт 25, 2015 19:09:46

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

Сообщение rusl32 »

misterkuk писал(а):Суть программы- автомобильный термометр на 4 канала.

А очистить в начале цикла LCD?

Добавлено after 2 minutes 19 seconds:
AndTer писал(а):Как можно осуществить сброс МК программно?
Асмовой командой безусловного перехода в нужное место.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

rusl32 писал(а):А очистить в начале цикла LCD?
категорически не советую - будет заметное мерцание дисплея.
AndTer писал(а):Как можно осуществить сброс МК программно?
многократно уже говорил и повторю: самый корректный способ программного сброса - это запретить прерывания, разрешить WDT и уйти в вечный цикл. примерно так:

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

   cli(); // запрет прерываний
   wdt_enable(); // разрешаем WDT
   while(1); // ждем сброса
переход "на начало кода" не является полным эквивалентом аппаратного сброса, и может быть рекомендован лишь в некоторых случаях, в то время как предлагаемый мною вариант может быть рекомендован всегда.

для педантов поясняю: сброс по WDT отличается от сброса по внешнему сигналу на входе RESET только установкой определенных флагов в определенном регистре (если таковой предусмотрен архитектурой МК). такое поведение документировано и может быть учтено в программе. иных отличий по "источнику" сброса нет.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
misterkuk
Мучитель микросхем
Сообщения: 400
Зарегистрирован: Сб апр 17, 2010 10:30:13
Контактная информация:

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

Сообщение misterkuk »

ARV писал(а):во-первых, не понятно, у вас графический или символьный ЖКИ?
HD44780 2004
у вас в коде анализа ошибочной ситуации нет, а должна быть.
Я же написал что делал анализ на ошибку. Даже с анализом выводятся 9ки. Значит температура с датчика считывается нормально, проходит проверку,, но после строки
sprintf( LcdBuff,"motor %.1f", ds18b20_temperature( &RomCode[1][0] ) ); получаются девятки.

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

t=ds18b20_temperature( &RomCode[1][0] ); //Считываем и записываем в переменную
if((t>=(-20)) && (t<=125)) // Проверяем на адекватность считанные данные. Проверку проходит нормально.
{
sprintf( LcdBuff,"motor %.1f", t);  // и вот тут в буфер уже помещаются деватки,  переодически
lcd_gotoxy(0,3);
lcd_puts(LcdBuff);
}


Чтобы решить первую проблему, достаточно при выводе строки всегда выводить одинаковое количество символов

Первая проблема не проблема вообще. Если девятки не будут выскакивать, то ничего лишнего не будет вылазить. Я слева хочу выводить температуру, а с права напряжение и еще чтонибуть.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

misterkuk писал(а):Первая проблема не проблема вообще. Если девятки не будут выскакивать, то ничего лишнего не будет вылазить.
ошибаетесь.
у вас такой код для вывода (кстати, почему не в цикле?)

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

         lcd_gotoxy(0,2);
         sprintf( LcdBuff,"pechka %.1f", ds18b20_temperature( &RomCode[2][0] ) );
         delay_us(50);
         lcd_puts(LcdBuff);         
в этом коде если температура была 10.5 градусов, а потом стала 9.5, вы увидите 9.55 ровно по той же причине, что и "хвост" от девяток. то, что вы еще этого не увидели - это временно. а правильные подходы дают всегда правильный результат. ваш код можно улучшить и иначе, чем советовал я, используя возможности форматированного вывода

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

 sprintf( LcdBuff,"pechka %6.1f", ds18b20_temperature( &RomCode[2][0] ) ); 
хотя внешне это может выглядеть не всегда красиво - это уж от вашего эстетства зависит

misterkuk писал(а):Я же написал что делал анализ на ошибку. Даже с анализом выводятся 9ки.
ну что я могу сказать... если сказанное вами правда, то я делаю только один вывод: не правильно делали. потому что просто не может быть девяток, если бы вы сделали так:

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

float temp;
temp =  ds18b20_temperature( &RomCode[2][0]);
if((temp > -60) && (temp < 150))  sprintf( LcdBuff,"pechka %.1f", temp);
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Ответить

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