Решил сделать окончательную версию КОТОФОНА (домофон для котов) и для этого собираю все на 1 проц и на одну плату. При написании кода столкнулся с предупреждением которое не могу победить : Предупреждение передача аргумента 1 ‘eeprom_update_dword’ преобразует указатель из целого числа без приведения . Много чего пробвал реализовать но видимо не все - удачных вариантов небыло. Если отбросить все лишнее по текту кода - то выглядит так ( но тоже не помогло):
Планировалось, что так я сохраняю в eeprom “ключи” разрешенные для прохода животных. Сработка открытия двери по сравнению текущего ключа с ключём в памяти, решил что 2-3 ключа будет достаточно, а хранение в eeprom начинаю с адреса 0x0100, а далее 0х0120 и 0х0140. - т.е. с шагом по 32 бита
(uint32_t IndividID; // 32-разрядная переменная для хранения индивидуального кода)
Сделайте, пожалуйста, так. Отбросьте всё лишнее, но таки оставьте короткий, но полный код, который я могу без лишних танцев с бубнами, запустить у себя и посмотреть, что там у Вас за предупреждение (тем более, что Вы, почему-то, его оригинальный текст скрываете).
/********************************************************************************************************************************************
ДВЕРЬ - собрал все - нужно проверить сохранение в памяти СЧИТЫВАНИЕ RFID МЕТОК СТАНДАРТА EM-MARINE НА 125 кГц И ПЕРЕДАЧА 5 БАЙТ ID-КОДА ЧЕРЕЗ UART
Версия 19.04.15
Для генерации сигнала частотой 125 кГц используется режим сброса по совпадению таймера 2
Генерация сигнала 125 кГц производится аппаратно на выводе ОС2 таймера 2 (в микроконтроллере ATmega16 - это вывод PD7)
Микроконтроллер ATmega16
Тактовая частота 8 MHz
********************************************************************************************************************************************/
#define F_CPU 8000000UL // Тактовая частота микроконтроллера
#include <avr/io.h>
#include <util/delay.h> // Библиотека программной задержки
#include <avr/eeprom.h> //подключение библиотеки работы с EEPROM
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ОСНОВНЫЕ КОНСТАНТЫ
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#define DDR_OPTIK DDRC // Определение регистров портов для оптических датчиков и управления блокировкой двери
#define PORT_OPTIK PORTC
#define PIN_OPTIK PINC
#define PIN_INCOMING PC0 // датчик положения двери
#define PIN_BOLT_UP PC1 // датчик верхнего открытого положения
#define PIN_BOLT_DOWN PC2 // датчик нижнего закрытого положения
#define PIN_OPEN PC3 // выход сигнала открытия двери
#define PIN_CLOSE PC4 // выход сигнала закрытия двери
#define BOLT_UP (PIN_OPTIK & (1<<PIN_BOLT_UP)) // высокий уровень датчика верхнего положения
#define BOLT_DOWN (PIN_OPTIK & (1<<PIN_BOLT_DOWN)) // высокий уровень датчика нижнего положения
#define INCOMING (PIN_OPTIK & (1<<PIN_INCOMING)) // высокий уровень датчик проходки
#define DDR_FREQ DDRD // Определение регистров портов для генерации частоты 125 кГц
#define PORT_RFID PORTD
#define PIN_RFID PIND
#define PIN_FREQ PD6 // Вывод для генерации несущей частоты 125 кГц (в микроконтроллере ATmega16 - это вывод PD7)
#define PIN_MEMORY PD4 // кнопка памяти ключа
#define RFID PD7 // Вывод для считывания manchester-кода с номером метки
#define SIGNAL_PIN (PIN_RFID & (1<<RFID)) // Значение логического уровня на выводе RFID
#define SAVE_IN_MEMORY (PIN_RFID & (1<<PIN_MEMORY)) // нажатие кнопки для сохранения ключа
#define BAUD 9600UL // Задание скорости обмена по UART
#define SPEED ((F_CPU+BAUD*8)/(BAUD*16)-1)
#define FREQ_OUT 125000UL // Частота генерируемая антеной считывателя, Гц
#define DIVIDER_125KHZ (F_CPU/FREQ_OUT/2-1) // Константа для генерации на выводе частоты FREQ_OUT от таймера 2
#define HALF_INTERVAL 370 // Полутерный интервал от короткого интервала в 250 мкс
#define HI 1 // Признак логической единицы
#define LO 0 // Признак логического нуля
#define OK 1 // Признак нормального завершения функции
#define ERR 0 // Признак завершения функции с ошибкой
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
uint8_t a=0;
uint8_t Level_Inv; // Переменная признака прямой/обратной логики
uint16_t Adress1=0x100;
uint16_t Adress2=0x120;
uint16_t Adress3=0x140;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ПРОТОТИПЫ ФУНКЦИЙ
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void out_UART (uint8_t);
uint8_t read_ID (uint8_t *, uint32_t *);
uint8_t Read_nibble (void);
uint8_t level_pin_rfid (void);
uint8_t Find_Preambula (void);
void Open_Door();
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// ОСНОВНОЙ КОД
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
int main(void)
{
DDR_OPTIK |=(0<<PIN_INCOMING|0<<PIN_BOLT_UP|0<<PIN_BOLT_DOWN|1<< PIN_OPEN|1<<PIN_CLOSE); //назначаем входы и выходы портадля управления дверью
DDR_FREQ |= (1<<PIN_FREQ); // Настраиваем вывод генерации сигнала FREQ_OUT от таймера на выход
OCR2 = DIVIDER_125KHZ; // В регистр совпадения заносится делитель для генерации частоты 125 кГц
TCCR2 = (1<<COM20|1<<WGM21|0<<CS22|0<<CS21|1<<CS20); // Настройка таймера на сброс по совпадению, деление 1
UCSRB = (1<<TXEN); // Настройка UART на передачу
UCSRC = (1<<URSEL|1<<UCSZ1|1<<UCSZ0);
UBRRL = SPEED & 0xFF;
UBRRH = SPEED >> 8;
while(1)
{
uint32_t IndividID; // 32-разрядная переменная для хранения индивидуального кода
uint8_t GroupID; // 8-разрядная переменная для хранения группового кода
if (read_ID(&GroupID, &IndividID) == OK){ // Если read_ID возвращает 1, значит код успешно считан
if(SAVE_IN_MEMORY) {
if(a==0){eeprom_update_dword(Adress1,IndividID);} // записать в eeprom при нажатой кнопке ?
//if(a==1){eeprom_update_dword(Adress2,IndividID);} // как оформить эту запись?
//if(a==2){eeprom_update_dword(Adress3,IndividID);}
a++;
if(a>2){a=0;} //ограничиваем количество сохраняемых ключей
}
out_UART(GroupID); // Отправка 8-разрядного группового кода
out_UART((uint8_t)(IndividID>>24)); // Отправка 4 байт индивидуального кода
out_UART((uint8_t)(IndividID>>16)); // Наблюдаем через терминал
out_UART((uint8_t)(IndividID>>8));
out_UART((uint8_t)(IndividID>>0));}
while(SAVE_IN_MEMORY){} // для однократной записи данных метки в память
if(eeprom_read_dword(Adress1==IndividID){ Open_Door();} // как сравнить текущее значение с данными в памяти
_delay_ms(1000); // Небольшая задержка, перед следующим циклом считывания
}
}
////////////////////////////////////////////////////////////
// СЧИТЫВАНИЕ ID-КОДА
////////////////////////////////////////////////////////////
uint8_t read_ID(uint8_t *Group, uint32_t *ID){
uint8_t data;
uint8_t xor = 0;
*Group = 0;
*ID = 0;
while (Find_Preambula() == ERR) {}; // Поиск преамбулы
// Чтение байта группового идентификатора
data = Read_nibble(); // Считываем первую тетраду
if (data & 0xF0) return ERR; // Если старшая тетрада равна 1111, значит контрольная сумма не сошлась
xor ^= data; // Вычисляем контролльную сумму
*Group = data<<4;
data = Read_nibble();
if (data & 0xF0) return ERR;
xor ^= data;
*Group |= data;
for (uint8_t i=0; i<8; i++){ // Цикл считывания 4 байт индивидуального кода
data = Read_nibble(); // Считываем тетраду
if (data & 0xF0) return ERR; // Если в 4 старших разрядах не ноль, следовательно произошла ошибка в считывании тетрады
xor ^= data; // Подсчет контрольной суммы
*ID |= ((uint32_t)data << (28-i*4)); // Записываем тетрады в 32-разрядное слово
}
data = Read_nibble(); // Считывание последние 4 бит контрольной суммы по столбцам
data &= 0x0F; // Обнуляем неиспользуемые биты ошибки в старшей тетраде
xor ^= data; // Исключающее ИЛИ подсчитанной контрольной суммы и считанной суммы по столбцам
if (xor) return ERR; // Если xor не равен нулю, то ошибка в подсчете контрльной суммы
else return OK; // Если xor равен нулю, то контрольная сумма подсчитана верно
}
////////////////////////////////////////////////////////////
// СЧИТЫВАНИЕ 5 БИТ СЛОТА
////////////////////////////////////////////////////////////
uint8_t Read_nibble(void){ // Чтение 5 бит слота (4 бита тетрады + 1 бит контрольной суммы)
uint8_t nibble = 0; // Переменная для приема тетрады
uint8_t xor = 0; // Переменная для подсчета контрольной суммы
for (uint8_t i=0; i<5; i++){
_delay_us(HALF_INTERVAL); // Ожидание полуторного короткого интервала
nibble <<= 1;
if (level_pin_rfid() == HI){ // Считали с вывода ноль
while (level_pin_rfid() != LO) {}; // Ожидание низкого уровня на выводе
}else{
nibble |= 1; // Считали с вывода единицу
xor ^= 1; // На рассчет контрольной суммы влияет только единица
while (level_pin_rfid() != HI) {}; // Ожидание высокого уровня на выводе
}//if
}//for
nibble >>= 1; // Избавились от 5-го бита контрольной суммы
if (xor){ // Если контрольная сумма не ноль, то ошибка чтения
nibble |= 0xF0; // В старших 4 битах возвращаем 1111 - признак ошибки
}
return nibble; // 4 бита считаны без ошибки. В старшей тетраде нули - признак схождения контрольной суммы
}
////////////////////////////////////////////////////////////
// НАХОЖДЕНИЕ ПРЕАМБУЛЫ
////////////////////////////////////////////////////////////
uint8_t Find_Preambula(){
Level_Inv = HI; // Признак прямой логики
for (uint8_t i=0; i<70; i++) // Цикл нахождения преамбулы в прямой логике
{
while (!SIGNAL_PIN) {}; // Ожидание высокого уровня на выводе
while (SIGNAL_PIN) {}; // Ожидание низкого уровня на выводе (ожидание спадающего фронта)
_delay_us(HALF_INTERVAL); // Ожидание полуторного короткого интервала после спадающего фронта
if (SIGNAL_PIN) continue; // Если на выводе высокий уровень, то ОШИБКА ЧТЕНИЯ ПРЕАМБУЛЫ
while (!SIGNAL_PIN) {}; // Ожидание высокого уровня на выводе
for (uint8_t j=0; j<8; j++){ // Цикл обнаружения признаков преамбулы
_delay_us(HALF_INTERVAL); // Ожидание полуторного короткого интервала
if (SIGNAL_PIN) break; // Если на выводе низкий уровень, то ОШИБКА ЧТЕНИЯ ПРЕАМБУЛЫ
while (!SIGNAL_PIN) {}; // Ожидание высокого уровня на выводе
if (j == 7) return OK; // Если 8 раз считаны логические 1 в прямой логике, то выходим из функции
}
}//for
Level_Inv = LO; // Признак обратной логики
for (uint8_t i=0; i<70; i++) // Цикл нахождения преамбулы в прямой логике
{
while (SIGNAL_PIN) {}; // Ожидание высокого уровня на выводе
while (!SIGNAL_PIN) {}; // Ожидание низкого уровня на выводе (ожидание спадающего фронта)
_delay_us(HALF_INTERVAL); // Ожидание полуторного короткого интервала после спадающего фронта
if (!SIGNAL_PIN) continue; // Если на выводе высокий уровень, то ОШИБКА ЧТЕНИЯ ПРЕАМБУЛЫ
while (SIGNAL_PIN) {}; // Ожидание высокого уровня на выводе
for (uint8_t j=0; j<8; j++){ // Цикл обнаружения признаков преамбулы
_delay_us(HALF_INTERVAL); // Ожидание полуторного короткого интервала
if (!SIGNAL_PIN) break; // Если на выводе низкий уровень, то ОШИБКА ЧТЕНИЯ ПРЕАМБУЛЫ
while (SIGNAL_PIN) {}; // Ожидание высокого уровня на выводе
if (j == 7) return OK; // Если 8 раз считаны логические 1 в обратной логике, то выходим из функции
}
}//for
return ERR;
}
////////////////////////////////////////////////////////////
//СЧИТЫВАНИЕ УРОВНЯ С ВЫВОДА С УЧЕТОМ ПРЯМОЙ/ОБРАТНОЙ ЛОГИКИ
////////////////////////////////////////////////////////////
uint8_t level_pin_rfid(void){
if (Level_Inv == HI){ // Прямая логика
if (SIGNAL_PIN) return HI;
else return LO;
}else{ // Обратная логика
if (SIGNAL_PIN) return LO;
else return HI;
}
}
//////////////////////////////////////////////////////////////
// ОТКРЫТИЕ ДВЕРИ //
//////////////////////////////////////////////////////////////
void Open_Door(){
PORT_OPTIK |=(1<<PIN_OPEN); //________________
while(!(PIN_OPTIK & (1<<PIN_BOLT_UP))){} //
PORT_OPTIK |=(0<<PIN_OPEN); // проверено на отладочной плате PinBoard 2
_delay_ms(500); // работа логики для управления люком проверена и
if(PIN_OPTIK & (1<<PIN_INCOMING)){while(PIN_OPTIK & (1<<PIN_INCOMING));} // исправно работает
PORT_OPTIK |=(1<<PIN_CLOSE); //
while(!(PIN_OPTIK & (1<<PIN_BOLT_DOWN))){} //
PORT_OPTIK |=(0<<PIN_CLOSE);
}
////////////////////////////////////////////////////////////
// ПРИЕМ/ПЕРЕДАЧА ДАННЫХ UART
////////////////////////////////////////////////////////////
void out_UART(uint8_t data){ // Передача байта через UART
while(!(UCSRA&(1<<UDRE))); // Ожидание готовности UART к передаче
UDR = data; // Запись в регистр UDR байта данных начинает процесс передачи
}
Совсем короткий быстро не выйдет, но есть полный - там все закоментарено , а в принципе могу самую заморочную переменную превратить в константу и тогда останется совсем немного строк. Это IndividID вокруг которой все наворочено - 32-битное значение
Ну, тогда или делайте не по быстрому, или извините.
Я вставил, запустил, она у меня в принципе не компилируется (Вы ведь даже тип МК не указали, у меня стоит 328 - говорит, что у неё таких регистров нет). А трахаться, смотреть что там за регистры, подбирать МК, чтобы оно как-то скомпилировалось … ну, вот, правда, мне это надо? Вот, вся эта головная боль? Сами-то как думаете?
Сделайте так, чтобы я мог просто запустить и увидеть Ваши ошибки без дополнительного траха - я Вам всё расскажу про указатели. Не можете, ну извините.
Мы с Вами никак не поймём друг друга. Я прошу нечто, что я могу взять и скомпилировать БЕЗ ТРАХА, без исправления Ваших кодов, просто взять и скомпилировать и увидеть Ваши ошибки.
Вы это компилировали? У Вас правда строка №20 компилируется? А строка №43 и дальше? У Вас это компилируется? А если нет, зачем Вы это мне дали? Чтобы что?
Вообще выше есть полный код, а эта порнуха просо чтоб по нужному условию хоть чтото тупое сделать , т.к. я сократил до минимума код. Главное как верно записать значение переменной uint32_t в адрес 100 ( начало eeprom у атмеги16) и как верно считать данное значение для сравнения с текущими данными.
Ок! понял - вижу преобразование типа, я ранее видел, что в библиотеке есть команда
eeprom_update_dword (uint32_t *__p, uint32_t __value), но ожидал, что адрес uint16_t просто дополниться нулями. Сейчас попробую исправить. Спасибо
Так я тоже попытался, но получил предупреждения в системе ( AtmelStudio 7.0)
ругается именно на эту строку и в конце сообщает об ошибке с незнакомой функцией.
Подскажите , какая библиотека используется в этом случае?