Вопросы по С/С++ (СИ)
Re: Вопросы по С/С++ (СИ)
Но в даташите же все прямым текстом написано!
- Реклама
- blackx
- Говорящий с текстолитом
- Сообщения: 1518
- Зарегистрирован: Пт дек 28, 2012 21:56:46
- Откуда: St. Petersburg
Re: Вопросы по С/С++ (СИ)
Как это относится к C/C++?
Если интересует как с этой микросхемы получить данные, изучайте фиг. 3 и 4 в даташите.
Если интересует как с этой микросхемы получить данные, изучайте фиг. 3 и 4 в даташите.
only pure true norwegian blackx 
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Есть небольшой вопрос по Си.
Как-то решил облегчить себе жизнь в одном проекте. Суть была в том, чтобы передать параметры из устройства на комп и с компа в устройство.
Всю конфигурацию устройства хранил в структуре, так удобнее работать:
На самом девайсе все ОК. Пишу структуру напрямую в EEPROM и читаю от туда тоже без всяких проблем. (Камень - AtMega32)
Копирую эту структуру в код в Visual Studio 2008
(код в компе)
Код в камне:
После недолгих раздумий перетасовал переменные в структуре (как в девайсе, так и в Windows)
После этого все заработало. (Предположения были на счет перестановки переменных компилятором в физической памяти. В других функциях ошибок небыло.)
То есть: Я использовал структуру как обычный массив. Упаковал его(массив) в пакет и отправил компу.
В компе указателю на структуру передавался адрес начала массива.
Следовательно вопрос: Хоть это и сработало, но стоит ли так делать? (Отправлять структуру как массив)
Насколько это переносимо между архитектурами с разной разрядностью? На сколько это надежно?
Как-то решил облегчить себе жизнь в одном проекте. Суть была в том, чтобы передать параметры из устройства на комп и с компа в устройство.
Всю конфигурацию устройства хранил в структуре, так удобнее работать:
Код: Выделить всё
typedef struct
{
uint16_t sign;
uint8_t param_1;
uint16_t param_2;
uint8_t param_3;
uint16_t param_4;
uint8_t param_5;
uint8_t param_6;
uint16_t param_7;
uint32_t crc32;
}cfg;
На самом девайсе все ОК. Пишу структуру напрямую в EEPROM и читаю от туда тоже без всяких проблем. (Камень - AtMega32)
Код: Выделить всё
cfg config;
....
EEPROMWrite((uint8_t*)&config, sizeof(config));
EEPROMRead((uint8_t*)&config, sizeof(config));
ConfigCheckCRC32(&config); // = true То есть Все ОК.
......
Копирую эту структуру в код в Visual Studio 2008
(код в компе)
Код: Выделить всё
bcount = BMSIReceive(buff); // Принимаю пакет
ParsePack(buff, bcount, (unsigned char*)&config, sizeof(config)); // Распаковываю данные
ConfigCheckCRC32(&config); // = false. То есть жопа.
Код в камне:
Код: Выделить всё
BMSISend(buff, (BuildPack(buff, (uint8_t*)&config, cmd, addr)));
После недолгих раздумий перетасовал переменные в структуре (как в девайсе, так и в Windows)
Код: Выделить всё
typedef struct
{
uint16_t sign;
uint16_t param_2;
uint16_t param_4;
uint16_t param_7;
uint8_t param_1;
uint8_t param_3;
uint8_t param_5;
uint8_t param_6;
uint32_t crc32;
}cfg;
После этого все заработало. (Предположения были на счет перестановки переменных компилятором в физической памяти. В других функциях ошибок небыло.)
То есть: Я использовал структуру как обычный массив. Упаковал его(массив) в пакет и отправил компу.
В компе указателю на структуру передавался адрес начала массива.
Следовательно вопрос: Хоть это и сработало, но стоит ли так делать? (Отправлять структуру как массив)
Насколько это переносимо между архитектурами с разной разрядностью? На сколько это надежно?
I am DX168B and this is my favourite forum on internet!
Re: Вопросы по С/С++ (СИ)
DX168B, это связано с выравниванием и "упаковкой" элементов структуры. В таких случаях надо чтобы компиляторы генерировали одинаковый код (раскладку, layout) структур.
В gcc (и для AVR в том числе) упаковка и выравнивание, скорее всего, производиться на 1. Можно принудительно указать с помощью опции компилятору -fpack-struct=1.
Соответственно и для Visual Studio вам надо аналогичные настройки сделать. Можно только для отдельной структуры, т.к. на x86 отсутствие выравнивания вообще может сильно замедлить работу программы.
В gcc (и для AVR в том числе) упаковка и выравнивание, скорее всего, производиться на 1. Можно принудительно указать с помощью опции компилятору -fpack-struct=1.
Соответственно и для Visual Studio вам надо аналогичные настройки сделать. Можно только для отдельной структуры, т.к. на x86 отсутствие выравнивания вообще может сильно замедлить работу программы.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
- Реклама
- blackx
- Говорящий с текстолитом
- Сообщения: 1518
- Зарегистрирован: Пт дек 28, 2012 21:56:46
- Откуда: St. Petersburg
Re: Вопросы по С/С++ (СИ)
Добавлю, что в gcc по умолчанию упаковка идет с выравниванием по тому количеству байт, которое занимает соответствующий тип. Например, вот тут
После переменной id в памяти будут расположены еще три неиспользованных байта. В итоге структура будет занимать не 5, а 8 байт. Когда вы переставили поля структуры, вы, по сути, избавились от всех таких "дырок". Вообще при любом упорядоченном расположении полей от самых больших по размеру к самым маленьким (типа int32_t > int16_t > int8_t) дырки образовываться не будут.
Код: Выделить всё
struct data {
uint8_t id;
uint32_t address;
};
После переменной id в памяти будут расположены еще три неиспользованных байта. В итоге структура будет занимать не 5, а 8 байт. Когда вы переставили поля структуры, вы, по сути, избавились от всех таких "дырок". Вообще при любом упорядоченном расположении полей от самых больших по размеру к самым маленьким (типа int32_t > int16_t > int8_t) дырки образовываться не будут.
only pure true norwegian blackx 
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Почему-то мне тоже так показалось (по поводу "дыр" в структурах) Все дело в том, что при отладке я заметил, что компилятор переставил переменные местами.
В итоге, в полях структуры были неправильные данные. Ну и соответственно чексумма не проходила.
Впредь буду знать, как еще можно сэкономить память и учитывать эти тонкости.
В итоге, в полях структуры были неправильные данные. Ну и соответственно чексумма не проходила.
Впредь буду знать, как еще можно сэкономить память и учитывать эти тонкости.
I am DX168B and this is my favourite forum on internet!
- urry
- Сверлит текстолит когтями
- Сообщения: 1262
- Зарегистрирован: Пн дек 08, 2008 10:58:48
- Откуда: Винница
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Как бы чуть дополняя последнего докладчика (последняя ссылка ) - живой код для вижуал
Код: Выделить всё
#pragma pack(push,1)// выравнивание по 1 байту
typedef struct sSingleMassPacket
{
unsigned char cMarker;
unsigned char cLenH;
unsigned char cLenL;
unsigned char cSend;
unsigned char cFrame;
unsigned char cAddr[10];
unsigned int iData;
sSingleMassPacket()// инициализация при создании
{
cMarker=0x7E;
cLenH=0;
cLenL=0x10;
cSend=0x10;
cFrame=0;
cAddr[0]=cAddr[1]=cAddr[2]=cAddr[3]=cAddr[4]=cAddr[5]=0;
cAddr[6]=cAddr[7]=cAddr[8]=0xFF;
cAddr[9]=0xFE;
iData=0;
}
}sSingleMassPacket;
#pragma pack(pop)
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
ОК. Спасибо.
Вопросы все отпали.
Подробнее мне надо было читать доки.
Вопросы все отпали.Подробнее мне надо было читать доки.
I am DX168B and this is my favourite forum on internet!
- Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
Добрый день
Или уже вечер 
На сей раз я вот с чем пришёл. Взял из клавиатуры прокручивающийся ролик (как на мышке). Собрал схемку.
ATmega32. Через этот ролик на ноги PC0 и PC1 при его покручивании чередуется +5в или 0.
Всё это затеяно для того, чтобы приобрести мало-мальский опыт в чтении портов.
И тут начинается непонятное.
DDRC=0b00000000;
Я объявляю 2 переменные:
int a=1;
int b=0;
После чего, в переменную а читается порт С:
a=PORTC; - правильно же?
это делается для того, чтобы знать, что происходит в порте при инициализации.
Далее (уже в цикле мэйн), я загружаю PORTC в b:
b=PORTB; - тоже, вроде бы, всё верно.
Далее идёт самое интересное.
if (a==b)
прибавлять выводимое на индикатор число на 1.
else
уменьшать выводимое на индикатор число на 1.
Теперь немного итогов. Изначально a и b не равны. a=0, b=1. Поэтому, если бы порт не читался, число бы уменьшалось. Но оно увеличивается, следовательно, a и b равны.
Далее, по идее, когда я кручу ролик, значение в порту меняется. Меняются его младшие 2 бита.
a остаётся таким, каким оно было в последний раз после команды a=PORTC.
Но b уже будет другим, тк загрузит в себя обновлённое значение PORTC.
Следовательно, a!=b и должен выполняться кусок else. Но этого не происходит. Опрос и вывод нового числа происходит через 1 сек.
Еще делал 2 эксперимента. Выводил на 7мисегментный индикатор напрямую порт С. Он показывает, что все биты равны 0.
Если обращаюсь через матрицу (то есть вывожу элемент, с номером порт С, он тоже показывает 0).
Я не понимаю чего-то очевидного? Подскажите, пожалуйста в очередной раз
На сей раз я вот с чем пришёл. Взял из клавиатуры прокручивающийся ролик (как на мышке). Собрал схемку.
ATmega32. Через этот ролик на ноги PC0 и PC1 при его покручивании чередуется +5в или 0.
Всё это затеяно для того, чтобы приобрести мало-мальский опыт в чтении портов.
И тут начинается непонятное.
DDRC=0b00000000;
Я объявляю 2 переменные:
int a=1;
int b=0;
После чего, в переменную а читается порт С:
a=PORTC; - правильно же?
это делается для того, чтобы знать, что происходит в порте при инициализации.
Далее (уже в цикле мэйн), я загружаю PORTC в b:
b=PORTB; - тоже, вроде бы, всё верно.
Далее идёт самое интересное.
if (a==b)
прибавлять выводимое на индикатор число на 1.
else
уменьшать выводимое на индикатор число на 1.
Теперь немного итогов. Изначально a и b не равны. a=0, b=1. Поэтому, если бы порт не читался, число бы уменьшалось. Но оно увеличивается, следовательно, a и b равны.
Далее, по идее, когда я кручу ролик, значение в порту меняется. Меняются его младшие 2 бита.
a остаётся таким, каким оно было в последний раз после команды a=PORTC.
Но b уже будет другим, тк загрузит в себя обновлённое значение PORTC.
Следовательно, a!=b и должен выполняться кусок else. Но этого не происходит. Опрос и вывод нового числа происходит через 1 сек.
Еще делал 2 эксперимента. Выводил на 7мисегментный индикатор напрямую порт С. Он показывает, что все биты равны 0.
Если обращаюсь через матрицу (то есть вывожу элемент, с номером порт С, он тоже показывает 0).
Я не понимаю чего-то очевидного? Подскажите, пожалуйста в очередной раз
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
Re: Вопросы по С/С++ (СИ)
Входные данные порта читаются не через PORTC а через PINC.
Тут про работу порта почитай http://easyelectronics.ru/avr-uchebnyj- ... yvoda.html
Тут про работу порта почитай http://easyelectronics.ru/avr-uchebnyj- ... yvoda.html
Последний раз редактировалось shads Чт июн 06, 2013 16:14:37, всего редактировалось 1 раз.
- Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
То есть b=PINC будет значить, взять все биты и этой команды будет достаточно? ТОгда до кучи ещё спрошу, как правильно прочитать какой-то отдельный бит? Большое спасибо!
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
Re: Вопросы по С/С++ (СИ)
Тут помоему чуть нагляднее про работу порта http://atsoftware.gb7.ru/blog/2013/04/a ... ортами-io/
Проверка бита 7 порта C:
Проверка бита 0 порта С:Мikа писал(а):То есть b=PINC будет значить, взять все биты и этой команды будет достаточно? ТОгда до кучи ещё спрошу, как правильно прочитать какой-то отдельный бит? Большое спасибо!
Код: Выделить всё
if (PINC & (1<<0))
придем сюда если значение бита равно 1;
else
придем сюда если значение бита равно 0;Проверка бита 7 порта C:
Код: Выделить всё
if (PINC & (1<<7))
придем сюда если значение бита равно 1;
else
придем сюда если значение бита равно 0;Re: Вопросы по С/С++ (СИ)
И кстати работа с энкодером не так проста как кажется..... а у тебя как я понял - именно энкодер......
viewtopic.php?f=20&t=76027&hilit=EncPrevPrev
Тут (почти в конце) процедурка от ЛИ которая может обрабатывать данные энкодера
viewtopic.php?f=20&t=76027&hilit=EncPrevPrev
Тут (почти в конце) процедурка от ЛИ которая может обрабатывать данные энкодера
Re: Вопросы по С/С++ (СИ)
Неоднократно мной проверенная... Применял во многих проектах.shads писал(а):Тут (почти в конце) процедурка от ЛИ которая может обрабатывать данные энкодера
С уважением,
Виктор.
Виктор.
- Мikа
- Потрогал лапой паяльник
- Сообщения: 343
- Зарегистрирован: Пн апр 01, 2013 15:13:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
Я посмотрел в Википедии что такое энкодер. Да, что-то вроде этого, но не так замудрено. У него 3 провода. Схема примерно такая:
a......b
|.......|
|.......|
/......./
|.......|
|.......|
|____|
....|
....|
....|
....c
Методом тыка установиЛ, что при единичном смещении (как бы один полный щёлк) происходит замыкание или размыкание ключей. В результате a и b подключаются или отключаются от c. Разница в направлении вращения сказывается очередностью вклдчений и выключений кнопок a и b.
a......b
|.......|
|.......|
/......./
|.......|
|.......|
|____|
....|
....|
....|
....c
Методом тыка установиЛ, что при единичном смещении (как бы один полный щёлк) происходит замыкание или размыкание ключей. В результате a и b подключаются или отключаются от c. Разница в направлении вращения сказывается очередностью вклдчений и выключений кнопок a и b.
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Потому что хочу научиться.
Re: Вопросы по С/С++ (СИ)
Пора уже от определений "полный щелк" переходить к временным диаграммам состояний контактов (в общем случае - сигналов) и их фазовым соотношениям. На уровне "кнопок" далеко не уйдете.Мikа писал(а):Я посмотрел в Википедии что такое энкодер. Да, что-то вроде этого, но не так замудрено. У него 3 провода. Схема примерно такая:
Методом тыка установиЛ, что при единичном смещении (как бы один полный щёлк) происходит замыкание или размыкание ключей. В результате a и b подключаются или отключаются от c. Разница в направлении вращения сказывается очередностью вклдчений и выключений кнопок a и b.
В Си команд работы с портами НЕТ. Это уже эмбеддеры для себя понапридумывали портов всяких...Скажите вот ещё что, есть ли в Си команда, которая выводит весь порт в переменную? Или если я хочу весь код, то надо написать процедурку(или как правильно),к оторая поочередно составит из всех PINxx байт или почти-байт?
А если серьезно, пора бы уже что-то и почитать, кроме постов в форуме. Потому как "выводить порт в переменную" - не наш метод.
С уважением,
Виктор.
Виктор.
Re: Вопросы по С/С++ (СИ)
Здравствуйте!
Помогите пожалуйста разобратся с АЦП атмеги8. Ранее в WinAVR как-то работал с ним, а щас в цвавре ника не могу сообразить.
Нашёл в качестве примера такой код:
скомпилировал, кинул в протеус, а тот мне reference value = 0 выдаёт в логе с ошибками, причём выдаёт многократно т.к. ошибка не фатальная. Что не так то с кодом
?
Помогите пожалуйста разобратся с АЦП атмеги8. Ранее в WinAVR как-то работал с ним, а щас в цвавре ника не могу сообразить.
Нашёл в качестве примера такой код:
Код: Выделить всё
#include <mega8.h>
#include <delay.h>
void main(void)
{
DDRB=0b00000001;
PORTB=0x00;
PORTC=0x00;
DDRC=0b00000000;
PORTD=0x00;
DDRD=0x00;
ADCSRA=0b10001110;
ADMUX=01000000;
#asm("sei")
while (1)
{
unsigned int aa;
ADCSRA |=0b01000000;
while ((ADCSRA&0b00010000)==0);
if (aa > 500) {PORTB = 0b00000001;} else {PORTB = 0b00000000;};
ADCSRA|= 0b00010000;
}
}
скомпилировал, кинул в протеус, а тот мне
Код: Выделить всё
while ((ADCSRA&0b00010000)==0);
?Re: Вопросы по С/С++ (СИ)
Вот сделал с конструктором.
Как только добавляю строку ADCSRA|=0b01000000; , то начинается такая - же байда. Если её не добавлять, то опрос АЦП производится только один раз, при включении.
Код: Выделить всё
#include <mega8.h>
#include <delay.h>
#define ADC_VREF_TYPE 0x40
unsigned int adc_data;
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
adc_data=ADCW;
}
void main(void)
{
PORTB=0x00;
DDRB=0b00000001;
ADMUX=ADC_VREF_TYPE & 0xf0;
ADCSRA=0x8E;
// Global enable interrupts
#asm("sei")
while (1)
{
ADCSRA|=0b01000000;
if (adc_data < 500) {PORTB = 0b00000001;} else {PORTB = 0b00000000;}
}
}
Как только добавляю строку ADCSRA|=0b01000000; , то начинается такая - же байда. Если её не добавлять, то опрос АЦП производится только один раз, при включении.


