Нескольно простых вопросов о программировании AVR на Си.

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

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение WiseLord »

По идее, sizeof(alarm) - размер всего массива. При i = 0 ещё куда ни шло, но дальше - выскакивает за пределы. Лучше не sizeof(alarm), а sizeof(alarm_t) здесь брать.

Хотя ещё проще, думаю, без цикла сразу всё считать:

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

eeprom_read_block(alarm, cp_alarm, sizeof(alarm));
Реклама
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение FreshMan »

есть некая функция меню при выходе из которой я записываю уставки в eeprom
если код размещен в таком порядке

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

	eeprom_update_byte (&cp_time_format, time_format);
	eeprom_update_byte (&cp_day_of_week, day_of_week);

	for(i=1; i<7; i++){
		eeprom_update_block( &alarm[i], &cp_alarm[i], sizeof(alarm) );
	}
то при последующем считывании переменных cp_time_format и cp_day_of_week в них оказывается какой-то мусор
а вот если код записать в таком порядке

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

	for(i=1; i<7; i++){
		eeprom_update_block( &alarm[i], &cp_alarm[i], sizeof(alarm) );
	}

	eeprom_update_byte (&cp_time_format, time_format);
	eeprom_update_byte (&cp_day_of_week, day_of_week);
то при последующем считывании cp_time_format и cp_day_of_week (которые дислоцируются в eeprom) в них находится ожидаемый результат
с чем это может быть связанно ?
Tell Me The Truth
Реклама
viiv
Грызет канифоль
Сообщения: 289
Зарегистрирован: Чт ноя 06, 2014 13:09:06

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение viiv »

FreshMan, Вам уже все подсказали.

Чему равно sizeof(alarm)?
Что сделает последняя итерация цикла eeprom_update_block( &alarm[6], &cp_alarm[6], sizeof(alarm) ); ??? Выходов за границы массивов нету???
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение WiseLord »

FreshMan: ещё раз перечитайте моё предыдущее сообщение.

А если так уж хочется цикл использовать, то пишите не кусками sizeof(alarm) (размер всех будильников), а меньшими sizeof(alarm_t) (размер одного будильника).
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение FreshMan »

WiseLord писал(а): Хотя ещё проще, думаю, без цикла сразу всё считать:

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

eeprom_read_block(alarm, cp_alarm, sizeof(alarm));
маленькое уточнение
вот как определена ф-ция в файле eeprom.h

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

void eeprom_read_block (void *__dst, const void *__src, size_t __n);
первые ее два аргумента являются указателями
почему вы тогда пишете eeprom_read_block(alarm, cp_alarm, sizeof(alarm)); а не eeprom_read_block(&alarm, &cp_alarm, sizeof(alarm)); ?
не ошибка ли это ?
Tell Me The Truth
Реклама
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение WiseLord »

Потому что и alarm, и cp_alarm - уже указатели на данные, которые надо копировать.

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

eeprom_read_block(alarm, cp_alarm, sizeof(alarm));
Здесь копируются sizeof(alarm) байт данных, лежащих по адресу cp_alarm, в место, на которое указывает alarm.
Нет, ну можно, конечно, написать иначе:

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

eeprom_read_block(&alarm[0], &cp_alarm[0], sizeof(alarm));
но зачем, если первый вариант короче и понятнее.
Реклама
Аватара пользователя
strengerst
Вымогатель припоя
Сообщения: 516
Зарегистрирован: Пт янв 18, 2013 15:11:02

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение strengerst »

Подскажите почему протеусс не видит этот код. Вот код на Disassembly.
Спойлер

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

--- No source file -------------------------------------------------------------
00000000  RJMP PC+0x0013		Relative jump 
00000001  RJMP PC+0x0022		Relative jump 
00000002  RJMP PC+0x0021		Relative jump 
00000003  RJMP PC+0x0020		Relative jump 
00000004  RJMP PC+0x001F		Relative jump 
00000005  RJMP PC+0x001E		Relative jump 
00000006  RJMP PC+0x001D		Relative jump 
00000007  RJMP PC+0x001C		Relative jump 
00000008  RJMP PC+0x001B		Relative jump 
00000009  RJMP PC+0x001A		Relative jump 
0000000A  RJMP PC+0x0019		Relative jump 
0000000B  RJMP PC+0x0018		Relative jump 
0000000C  RJMP PC+0x0017		Relative jump 
0000000D  RJMP PC+0x0016		Relative jump 
0000000E  RJMP PC+0x0015		Relative jump 
0000000F  RJMP PC+0x0014		Relative jump 
00000010  RJMP PC+0x0013		Relative jump 
00000011  RJMP PC+0x0012		Relative jump 
00000012  RJMP PC+0x0011		Relative jump 
00000013  CLR R1		Clear Register 
00000014  OUT 0x3F,R1		Out to I/O location 
00000015  LDI R28,0x5F		Load immediate 
00000016  LDI R29,0x04		Load immediate 
00000017  OUT 0x3E,R29		Out to I/O location 
00000018  OUT 0x3D,R28		Out to I/O location 
00000019  LDI R18,0x00		Load immediate 
0000001A  LDI R26,0x60		Load immediate 
0000001B  LDI R27,0x00		Load immediate 
0000001C  RJMP PC+0x0002		Relative jump 
0000001D  ST X+,R1		Store indirect and postincrement 
0000001E  CPI R26,0x61		Compare with immediate 
0000001F  CPC R27,R18		Compare with carry 
00000020  BRNE PC-0x03		Branch if not equal 
00000021  RCALL PC+0x0003		Relative call subroutine 
00000022  RJMP PC+0x0077		Relative jump 
00000023  RJMP PC-0x0023		Relative jump 
--- C:\Users\st\Documents\Atmel Studio\6.1\USART8ATmega2\USART8ATmega2\Debug/.././USART8ATmega2.c 
{
00000024  PUSH R28		Push register on stack 
00000025  PUSH R29		Push register on stack 
00000026  IN R28,0x3D		In from I/O location 
00000027  IN R29,0x3E		In from I/O location 
--- C:\Users\st\Documents\Atmel Studio\6.1\USART8ATmega2\USART8ATmega2\Debug/.././USART8ATmega2.c 
	PORTD|=(1<<PD1);
00000028  LDI R24,0x32		Load immediate 
00000029  LDI R25,0x00		Load immediate 
0000002A  LDI R18,0x32		Load immediate 
0000002B  LDI R19,0x00		Load immediate 
0000002C  MOVW R30,R18		Copy register pair 
0000002D  LDD R18,Z+0		Load indirect with displacement 
0000002E  ORI R18,0x02		Logical OR with immediate 
0000002F  MOVW R30,R24		Copy register pair 
00000030  STD Z+0,R18		Store indirect with displacement 
	UCSRB|=(1<<TXEN);
00000031  LDI R24,0x2A		Load immediate 
00000032  LDI R25,0x00		Load immediate 
00000033  LDI R18,0x2A		Load immediate 
00000034  LDI R19,0x00		Load immediate 
00000035  MOVW R30,R18		Copy register pair 
00000036  LDD R18,Z+0		Load indirect with displacement 
00000037  ORI R18,0x08		Logical OR with immediate 
00000038  MOVW R30,R24		Copy register pair 
00000039  STD Z+0,R18		Store indirect with displacement 
	UCSRC|=(1<<URSEL);
0000003A  LDI R24,0x40		Load immediate 
0000003B  LDI R25,0x00		Load immediate 
0000003C  LDI R18,0x40		Load immediate 
0000003D  LDI R19,0x00		Load immediate 
0000003E  MOVW R30,R18		Copy register pair 
0000003F  LDD R18,Z+0		Load indirect with displacement 
00000040  ORI R18,0x80		Logical OR with immediate 
00000041  MOVW R30,R24		Copy register pair 
00000042  STD Z+0,R18		Store indirect with displacement 
	UCSRC|=(1<<UCSZ1)|(1<<UCSZ0);
00000043  LDI R24,0x40		Load immediate 
00000044  LDI R25,0x00		Load immediate 
00000045  LDI R18,0x40		Load immediate 
--- C:\Users\st\Documents\Atmel Studio\6.1\USART8ATmega2\USART8ATmega2\Debug/.././USART8ATmega2.c 
00000046  LDI R19,0x00		Load immediate 
00000047  MOVW R30,R18		Copy register pair 
00000048  LDD R18,Z+0		Load indirect with displacement 
00000049  ORI R18,0x06		Logical OR with immediate 
0000004A  MOVW R30,R24		Copy register pair 
0000004B  STD Z+0,R18		Store indirect with displacement 
	UCSRC&=~(1<<UMSEL);
0000004C  LDI R24,0x40		Load immediate 
0000004D  LDI R25,0x00		Load immediate 
0000004E  LDI R18,0x40		Load immediate 
0000004F  LDI R19,0x00		Load immediate 
00000050  MOVW R30,R18		Copy register pair 
00000051  LDD R18,Z+0		Load indirect with displacement 
00000052  ANDI R18,0xBF		Logical AND with immediate 
00000053  MOVW R30,R24		Copy register pair 

А вот что видит Proteus

Все разобрался вся проблема заключается в том что Proteus отказывается работать с файлами написанными на С. А работает с файлами написанными на С++. Надо так же зайти в Edit Sourch code и загрузить в эмулятор кода Win AVR, он читает С код.
Вложения
prot21.png
(70.7 КБ) 363 скачивания
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение FreshMan »

как сделать так чтобы ф-ция обявленная с одним аргументом типа uint8_t принимала параметры типа uint8_t или int8_t ?
Tell Me The Truth
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение WiseLord »

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

uint8_t par1;
int8_t par2;

func(par1);
func((uint8_t)par2);
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение FreshMan »

uint8_t х;
void set_value (int8_t *var, uint8_t max, uint8_t min); - прототип
надо сделать так
set_value (&x, 100, 10);
но чтобы х в ф-ции был int8_t
Tell Me The Truth
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ptr128 »

FreshMan писал(а):параметры типа uint8_t или int8_t ?
Встречный вопрос. Если переменная типа int8_t имеет текущее значение -1 (минус единица), то что Вы хотите передать в функцию?
255 или 1?

Добавлено after 5 minutes 21 second:
FreshMan писал(а):uint8_t х;
void set_value (int8_t *var, uint8_t max, uint8_t min); - прототип
надо сделать так
set_value (&x, 100, 10);
но чтобы х в ф-ции был int8_t
А он и будет в функции интерпретироваться в соответствии с описанием типа в прототипе функции. То есть, как int8_t
Другой вопрос, что это может привести к проблемам, так как любое восьмибитное беззнаковое число большее 127 окажется в вызываемой функции отрицательным.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение FreshMan »

переменная uint8_t х; вне ф-ции set_value (int8_t *var, uint8_t max, uint8_t min); никогда не принимкает отрицательные значения
просто мне надо, к примеру сделать вызов с такими параметрами set_value (&x, 100, 0);
внутри этой ф-ции я анализирую
if (--*var < min) *var = max;
для того я и делаю ее типа int8_t дабы узнать когда она станет меньше 0 и присвоить ей макс значение
Tell Me The Truth
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ptr128 »

FreshMan писал(а):переменная uint8_t х никогда не принимкает отрицательные значения
А беззнаковая переменная по определению не может принимать отрицательных значений.
Похоже, у Вас недопонимание в теории.
С точки зрения подавляющего большинства CPU (предположу даже, что всех современных) и AVR в том числе, целые числа в памяти вообще не разделяются на знаковые или беззнаковые. С точки зрения CPU и uint8_t и int8_t - одно и тоже. Просто байт. Восемь бит.
Однако для работы со знаковыми и безнаковыми числами существуют различные машинные команды. Беззнаковые команды оперируют целиком с 8 битами. А вот знаковые анализируют самый старший бит. Если этот бит нулевой - число не отрицательное (положительное или ноль). Еcли единица - то отрицательное. Причем отрицательное в дополнительном коде.
То есть, значения от 0 до 127 будут считаться знаковой командой положительными. А вот уже беззнаковое 128 будет считаться знаковым -128. Беззнаковое 255 будет считаться знаковой -1.
Иными словами сравнивая два байта, содержащие значения 200 и 100, как беззнаковые числа, Вы получите, что первое больше второго. Сравнивая эти же два байта, как знаковые числа, результат будет противоположным - первое меньше второго.
Чуть не забыл. Сравнить знаковое число с беззнаковым у Вас вообще не получится по той простой причине, что если в выражении компилятор встречает знаковое и беззнаковое число, то знаковое будет преобразовано в беззнаковое. То есть сравнение знакового числа с беззнаковым всегда эквивалентно сравнению беззнаковых чисел.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18548
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ARV »

FreshMan писал(а):делаю ее типа int8_t дабы узнать когда она станет меньше 0 и присвоить ей макс значение

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

uint8_t *x;

if(*x) (*x)--;
else *x = MAX_VAL;
не нужно лишних преобразований типов
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ptr128 »

FreshMan писал(а):мне надо, к примеру сделать вызов с такими параметрами set_value (&x, 100, 0);
Насколько я понял Вашу цель, то код такой:

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

#define MY_SET_VALUE(var,min,max) var=(var<=min)?max:var-1

void main(void)
{
  uint8_t x;
...
  MY_SET_VALUE(x,10,100);
}
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение FreshMan »

попробую изясниться более четко
есть функция

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

void set_value (int8_t *var, uint8_t max, uint8_t min){

	if ( button_1) {
		
		if (++*var > max) *var = min;
	}


	if (button_2) {

		if (--*var < min) *var = max;
	}

}
я ее использую только при заходе в меню
где двигаясь попунктам (они организованы в виде оператора switch) я тем самым вызываю ф-цию set_value (int8_t *var, uint8_t max, uint8_t min) с разными параметрами
когда мне надо некий параметр регулировать от 100 до 1 то тут проблем нет
а вот когда его надо регулировать от 100 до 0 (ВКЛЮЧИТЕЛЬНО) то тут и начинаются траблы,
поскольку код if (--*var < min) *var = max; уже работает не коректно т.к. если сделать декремент ноля то мы получим 255
Tell Me The Truth
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18548
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ARV »

я же вам показал, как примерно следует поступать:

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

if(x) x--; // если х не равен нулю - уменьшаем его
else x = max; // а если равен - делаем максимальнм
Добавлено after 1 minute 40 seconds:
кстати, для системы меню на ЖКИ 16х2/4 могу предложить мои наработки, где все вопрос "регулирования" параметров уже решены.
правда для не-ЖКИ версии применить будет практически нереально...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
ptr128
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Чт окт 06, 2016 21:12:07
Откуда: Южное Бутово

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ptr128 »

FreshMan писал(а): а вот когда его надо регулировать от 100 до 0 (ВКЛЮЧИТЕЛЬНО)
Вместо

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

		if (++*var > max) *var = min;
		if (--*var < min) *var = max;
сделайте

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

		if ((*var)++ >= max) *var = min;
		if ((*var)-- <= min) *var = max;
соответственно.
Не ошибается только то, кто ничего не делает.
Тот, кто признает свои ошибки, на них учится.
Глупец же, упорствуя в своих заблуждениях, остается глупцом.
Аватара пользователя
FreshMan
Друг Кота
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение FreshMan »

прошу совета
пишу ф-цию преобразования HSV в RGB
https://ru.wikipedia.org/wiki/HSV_(цветовая_модель)
Изображение
для того чтобы выходной результат получился не в процентах а ввиде числа от 0 до 255 его следует умножать на 2.55
Изображение
можна ли сдесь обойтись без подключении либы для работы с плавающей точкой ?
память почти на пределе :(
Tell Me The Truth
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Reflector »

FreshMan писал(а):для того чтобы выходной результат получился не в процентах а ввиде числа от 0 до 255 его следует умножать на 2.55
Изображение
можна ли сдесь обойтись без подключении либы для работы с плавающей точкой ?
Если совсем по-простому, то представляешь младшие 8 бит как дробную часть, а старшие - как целую. Т.е. 512 - это 2, 64 - это 0.25, 512 + 64 - это 2.25. Тогда 0.55 - это 141 (0.55 / (1/256)). Тут уже будет погрешность, но можно под дробную часть выделить любое количество бит, например, 16. Теперь берем любое число, пусть это будет 7, множим на 141, получаем 987, добавляем 128(0.5), чтобы округлить в большую сторону, делим на 256, ответ 4(должно быть 3.85).
Ответить

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