Помогите с программированием
- Войдите на сайт для отправки комментариев
Вс, 29/07/2018 - 15:56
Пытаюсь запустить данный сенцор без библиотеки ( https://learn.sparkfun.com/tutorials/apds-9301-sensor-hookup-guide) но при выдаче получаю всегда одно и тоже число ( Luminous flux: 1223223), с библиотекой все работает.
Помогите найти ошибку в коде.
(APDS-9301 Sensor)
#include <Wire.h> #include "Arduino.h" #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif #define INT_PIN 2 bool lightIntHappened = false; #define CONTROL_REG 0x80 #define TIMING_REG 0x81 #define THRESHLOWLOW_REG 0x82 #define THRESHLOWHI_REG 0x83 #define THRESHHILOW_REG 0x84 #define THRESHHIHI_REG 0x85 #define INTERRUPT_REG 0x86 #define ID_REG 0x8A #define DATA0LOW_REG 0x8C #define DATA0HI_REG 0x8D #define DATA1LOW_REG 0x8E #define DATA1HI_REG 0x8F typedef enum {LOW_GAIN, HIGH_GAIN} gain; typedef enum {INT_TIME_13_7_MS, INT_TIME_101_MS, INT_TIME_402_MS} intTime; typedef enum {SUCCESS, I2C_FAILURE} status; typedef enum {INT_OFF, INT_ON} interruptEnable; typedef enum {POW_OFF, POW_ON} powEnable; status begin(uint8_t address); status powerEnable(powEnable powEn); status setGain(gain gainLevel); status setIntegrationTime(intTime integrationTime); status enableInterrupt(interruptEnable intMode); status clearIntFlag(); status setCyclesForInterrupt(uint8_t cycles); status setLowThreshold(unsigned int threshold); status setHighThreshold(unsigned int threshold); uint8_t getIDReg(); gain getGain(); intTime getIntegrationTime(); uint8_t getCyclesForInterrupt(); unsigned int getLowThreshold(); unsigned int getHighThreshold(); unsigned int readCH0Level(); unsigned int readCH1Level(); float readLuxLevel(); uint8_t address; uint8_t A; uint8_t getRegister(uint8_t regAddress); status setRegister(uint8_t regAddress, uint8_t newVal); uint16_t getTwoRegisters(uint8_t regAddress); status setTwoRegisters(uint8_t regAddress, uint16_t newVal); void setup() { delay(2500); Serial.begin(115200); Wire.begin(); // APDS9301 sensor setup. begin(0x39); setGain(LOW_GAIN); setIntegrationTime(INT_TIME_13_7_MS); setLowThreshold(0); setHighThreshold(50); setCyclesForInterrupt(34); enableInterrupt(INT_ON); clearIntFlag(); pinMode(INT_PIN, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(2), lightInt, FALLING); Serial.println(getLowThreshold()); Serial.println(getHighThreshold()); } void loop() { //Serial.read(); static unsigned long outLoopTimer = 0; clearIntFlag(); if (millis() - outLoopTimer >= 2000) { outLoopTimer = millis(); Serial.print("Luminous flux: "); Serial.println(readCH0Level(),6); if (lightIntHappened) { Serial.println("Interrupt"); lightIntHappened = false; } } } void lightInt() { lightIntHappened = true; } status begin(uint8_t A) { A = address; powerEnable(POW_ON); //APDS9301::status result = setGain(HIGH_GAIN); //if (setIntegrationTime(INT_TIME_402_MS) != SUCCESS) result = I2C_FAILURE; //return result; return SUCCESS; } status powerEnable(powEnable powEn) { if (powEn == POW_OFF) return setRegister(CONTROL_REG, 0); else return setRegister(CONTROL_REG, 3); } status setGain(gain gainLevel) { uint8_t regVal = getRegister(TIMING_REG); if (gainLevel == LOW_GAIN) regVal &= ~0x10; else regVal |= 0x10; return setRegister(TIMING_REG, regVal); } status setIntegrationTime(intTime integrationTime) { uint8_t regVal = getRegister(TIMING_REG); regVal &= ~0x03; if (integrationTime == INT_TIME_13_7_MS) regVal |= 0x00; else if (integrationTime == INT_TIME_101_MS) regVal |= 0x01; else if (integrationTime == INT_TIME_402_MS) regVal |= 0x02; return setRegister(TIMING_REG, regVal); } status enableInterrupt(interruptEnable intMode) { uint8_t regVal = getRegister(INTERRUPT_REG); // This is not a typo- OFF requires bits 4&5 to be cleared, but // ON only requires bit 4 to be set. I dunno why. if (intMode == INT_OFF) regVal &= ~0x30; else regVal |= 0x10; return setRegister(INTERRUPT_REG, regVal); } status clearIntFlag() { Wire.beginTransmission(A); Wire.write(0xC0); status retVal; if (Wire.endTransmission() == 0) return SUCCESS; else return I2C_FAILURE; } status setCyclesForInterrupt(uint8_t cycles) { uint8_t regVal = getRegister(INTERRUPT_REG); regVal &= ~0x0F; // clear lower four bits of register cycles &= ~0xF0; // ensure top four bits of data are clear regVal |= cycles; // Sets any necessary bits in regVal. return setRegister(INTERRUPT_REG, regVal); } status setLowThreshold(unsigned int threshold) { int retVal = setTwoRegisters(THRESHLOWLOW_REG, threshold); if (retVal == 0) return SUCCESS; else return I2C_FAILURE; } status setHighThreshold(unsigned int threshold) { int retVal = setTwoRegisters(THRESHHILOW_REG, threshold); if (retVal == 0) return SUCCESS; else return I2C_FAILURE; } uint8_t getIDReg() { return getRegister(ID_REG); } gain getGain() { uint8_t regVal = getRegister(TIMING_REG); regVal &= 0x10; if (regVal != 0) return HIGH_GAIN; else return LOW_GAIN; } intTime getIntegrationTime() { uint8_t regVal = getRegister(TIMING_REG); regVal &= 0x03; if (regVal == 0x00) return INT_TIME_13_7_MS; else if (regVal == 0x01) return INT_TIME_101_MS; else return INT_TIME_402_MS; } uint8_t getCyclesForInterrupt() { uint8_t regVal = getRegister(INTERRUPT_REG); regVal &= ~0x0F; return regVal; } unsigned int getLowThreshold() { unsigned int retVal = getRegister(THRESHLOWHI_REG)<<8; retVal |= getRegister(THRESHLOWLOW_REG); return retVal; } unsigned int getHighThreshold() { unsigned int retVal = getRegister(THRESHHIHI_REG)<<8; retVal |= getRegister(THRESHHILOW_REG); return retVal; } unsigned int readCH0Level() { return getTwoRegisters(DATA0LOW_REG); } unsigned int readCH1Level() { return getTwoRegisters(DATA1LOW_REG); } float readLuxLevel() { unsigned int ch1Int = readCH1Level(); unsigned int ch0Int = readCH0Level(); float ch0 = (float)readCH0Level(); float ch1 = (float)readCH1Level(); switch (getIntegrationTime()) { case INT_TIME_13_7_MS: if ((ch1Int >= 5047) || (ch0Int >= 5047)) { return 1.0/0.0; } break; case INT_TIME_101_MS: if ((ch1Int >= 37177) || (ch0Int >= 37177)) { return 1.0/0.0; } break; case INT_TIME_402_MS: if ((ch1Int >= 65535) || (ch0Int >= 65535)) { return 1.0/0.0; } break; } float ratio = ch1/ch0; switch (getIntegrationTime()) { case INT_TIME_13_7_MS: ch0 *= 1/0.034; ch1 *= 1/0.034; break; case INT_TIME_101_MS: ch0 *= 1/0.252; ch1 *= 1/0.252; break; case INT_TIME_402_MS: ch0 *= 1; ch1 *= 1; break; } if (getGain() == LOW_GAIN) { ch0 *= 16; ch1 *= 16; } float luxVal = 0.0; if (ratio <= 0.5) { luxVal = (0.0304 * ch0) - ((0.062 * ch0) * (pow((ch1/ch0), 1.4))); } else if (ratio <= 0.61) { luxVal = (0.0224 * ch0) - (0.031 * ch1); } else if (ratio <= 0.8) { luxVal = (0.0128 * ch0) - (0.0153 * ch1); } else if (ratio <= 1.3) { luxVal = (0.00146 * ch0) - (0.00112*ch1); } return luxVal; return 0; } uint8_t getRegister(uint8_t regAddress) { Wire.beginTransmission(A); Wire.write(regAddress); Wire.endTransmission(false); Wire.requestFrom(A, (uint8_t)1); return Wire.read(); } uint16_t getTwoRegisters(uint8_t regAddress) { Wire.beginTransmission(A); Wire.write(0x20 | regAddress); Wire.endTransmission(false); Wire.requestFrom(A, (uint8_t)2); uint16_t regVal = Wire.read(); return regVal | (Wire.read()<<8); } status setRegister(uint8_t regAddress, uint8_t newVal) { Wire.beginTransmission(A); Wire.write(regAddress); Wire.write(newVal); if (Wire.endTransmission() == 0) return SUCCESS; else return I2C_FAILURE; } status setTwoRegisters(uint8_t regAddress, uint16_t newVal) { Wire.beginTransmission(A); Wire.write(0x20 | regAddress); Wire.write((uint8_t)newVal); Wire.write((uint8_t)(newVal>>8)); if (Wire.endTransmission() == 0) return SUCCESS; else return I2C_FAILURE; }А чем Вас не устраивает бибилиотека, если с нею всё работает? Она делает как-то не так? А если так, то что мешает посмотреть как делает она и сделать также?
мне надо без, я делал с ее помощью,но по видемому где то допустил ошибку
"без" - у Вас гораздо больше шансов допустить не одну, а сразу много ошибок.
Но, в принципе, ЕвгенийП изложил самый прстой вариант переделки: посмотриеть в библиотеке и сделать так же. Есть еще более правильный вариант: изучить дэйташит и, основываясь на нем, самостоятельно написать библиотеку. Но он обычно бывает сложнее.
я делал как в библиотеке, то есть ,практически скопировал ее, но видемо где то ошибка , не могу понять где
не могу понять где
Ну, если уж Вы, человек, который видит эту библиотеку, не можете понять, то нам-то как понимать, если мы понятия не имеем, что за библиотека и никогда её не видели? Мы и подавно не поймём.
Не поленитесь, создайте комментарии к Вашей программе. Нам станет понятнее, ну и может Вы сами найдете ошибку.
Автор, прекращайте заниматься ерундой. Если Вам нужно работать с этим датчиком - используйте библиотеку!
Ну а для начала посмотрите на вызов функции в строке 68 и на саму функцию - строки 118, 120.
мне надо без
Библиотеки для того и пишутся, чтобы те, кто не умеет делать сам, могли ими пользоваться. Ты, похоже, не умеешь, но зачем-то тебе обязательно надо без библиотеки. Зачем? Чем она тебя не устраивает? Можешь толково объяснить?
И, да, тебе тут уже говорили, пока ты будешь сидеть как партизан и секретить что там за библиотека, тебе никто и ничто не поможет.
Привет,мне по заданию мне надо не пользоваться библиотеками.
https://github.com/sparkfun/APDS-9301_Breakout/tree/master/Libraries/Ard...
с этого сайта я взял библиотеки.
gentlemanOP, так кому задали задание, Вам или кому-то другому?
И не надо делать вид, будто Вы считаете, что форум нужен для того, чтобы кто-то делал задания за нерадивых студентов.
ДА мне. я решил сделат все с 0 , сообщу вам о успехах
status setTwoRegisters(uint8_t regAddress, uint16_t newVal); status setHighThreshold(unsigned int threshold); status setCyclesForInterrupt(uint8_t cycles); status enableInterrupt(interruptEnable intMode); unsigned int getLowThreshold(); unsigned int getHighThreshold(); unsigned int readCH0Level(); unsigned int readCH1Level(); uint8_t address; uint8_t getIDReg(); uint8_t getRegister(uint8_t regAddress); uint16_t getTwoRegisters(uint8_t regAddress); uint8_t getCyclesForInterrupt(); gain getGain(); status clearIntFlag(); float readLuxLevel(); intTime getIntegrationTime(); void lightInt() { lightIntHappened = true; } void setup() { delay(5); // The CCS811 wants a brief delay after startup. Serial.begin(115200); Wire.begin(); begin(0x39); setGain(LOW_GAIN); setIntegrationTime(INT_TIME_13_7_MS); setLowThreshold(0); setHighThreshold(50); setCyclesForInterrupt(1); enableInterrupt(INT_ON); clearIntFlag(); pinMode(INT_PIN, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(2), lightInt, FALLING); Serial.println(getLowThreshold()); Serial.println(getHighThreshold()); } void loop() { static unsigned long outLoopTimer = 0; clearIntFlag(); if (millis() - outLoopTimer >= 1000) { outLoopTimer = millis(); Serial.print("Luminous flux: "); Serial.println(readCH0Level(),6); if (lightIntHappened) { Serial.println("Interrupt"); lightIntHappened = false; } } } status begin(uint8_t address) { // this->address = address; powerEnable(POW_ON); status result = setGain(HIGH_GAIN); if (setIntegrationTime(INT_TIME_402_MS) != SUCCESS) result = I2C_FAILURE; return result; return SUCCESS; } status powerEnable(powEnable powEn) { if (powEn == POW_OFF) return setRegister(CONTROL_REG, 0); else return setRegister(CONTROL_REG, 3); } status setRegister(uint8_t regAddress, uint8_t newVal) { Wire.beginTransmission(address); Wire.write(regAddress); Wire.write(newVal); if (Wire.endTransmission() == 0) return SUCCESS; else return I2C_FAILURE; } status setGain(gain gainLevel) { uint8_t regVal = getRegister(TIMING_REG); if (gainLevel == LOW_GAIN) regVal &= ~0x10; else regVal |= 0x10; return setRegister(TIMING_REG, regVal); } uint8_t getRegister(uint8_t regAddress) { Wire.beginTransmission(address); Wire.write(regAddress); Wire.endTransmission(false); Wire.requestFrom(address, (uint8_t)1); return Wire.read(); } status setIntegrationTime(intTime integrationTime) { uint8_t regVal = getRegister(TIMING_REG); regVal &= ~0x03; if (integrationTime == INT_TIME_13_7_MS) regVal |= 0x00; else if (integrationTime == INT_TIME_101_MS) regVal |= 0x01; else if (integrationTime == INT_TIME_402_MS) regVal |= 0x02; return setRegister(TIMING_REG, regVal); } status setLowThreshold(unsigned int threshold) { int retVal = setTwoRegisters(THRESHLOWLOW_REG, threshold); if (retVal == 0) return SUCCESS; else return I2C_FAILURE; } status setTwoRegisters(uint8_t regAddress, uint16_t newVal) { Wire.beginTransmission(address); Wire.write(0x20 | regAddress); Wire.write((uint8_t)newVal); Wire.write((uint8_t)(newVal>>8)); if (Wire.endTransmission() == 0) return SUCCESS; else return I2C_FAILURE; } status setHighThreshold(unsigned int threshold) { int retVal = setTwoRegisters(THRESHHILOW_REG, threshold); if (retVal == 0) return SUCCESS; else return I2C_FAILURE; } status setCyclesForInterrupt(uint8_t cycles) { uint8_t regVal = getRegister(INTERRUPT_REG); regVal &= ~0x0F; // clear lower four bits of register cycles &= ~0xF0; // ensure top four bits of data are clear regVal |= cycles; // Sets any necessary bits in regVal. return setRegister(INTERRUPT_REG, regVal); } status enableInterrupt(interruptEnable intMode) { uint8_t regVal = getRegister(INTERRUPT_REG); // This is not a typo- OFF requires bits 4&5 to be cleared, but // ON only requires bit 4 to be set. I dunno why. if (intMode == INT_OFF) regVal &= ~0x30; else regVal |= 0x10; return setRegister(INTERRUPT_REG, regVal); } status clearIntFlag() { Wire.beginTransmission(address); Wire.write(0xC0); status retVal; if (Wire.endTransmission() == 0) return SUCCESS; else return I2C_FAILURE; } uint8_t getIDReg() { return getRegister(ID_REG); } gain getGain() { uint8_t regVal = getRegister(TIMING_REG); regVal &= 0x10; if (regVal != 0) return HIGH_GAIN; else return LOW_GAIN; } intTime getIntegrationTime() { uint8_t regVal = getRegister(TIMING_REG); regVal &= 0x03; if (regVal == 0x00) return INT_TIME_13_7_MS; else if (regVal == 0x01) return INT_TIME_101_MS; else return INT_TIME_402_MS; } uint8_t getCyclesForInterrupt() { uint8_t regVal = getRegister(INTERRUPT_REG); regVal &= ~0x0F; return regVal; } unsigned int getLowThreshold() { unsigned int retVal = getRegister(THRESHLOWHI_REG)<<8; retVal |= getRegister(THRESHLOWLOW_REG); return retVal; } unsigned int getHighThreshold() { unsigned int retVal = getRegister(THRESHHIHI_REG)<<8; retVal |= getRegister(THRESHHILOW_REG); return retVal; } unsigned int readCH0Level() { return getTwoRegisters(DATA0LOW_REG); } unsigned int readCH1Level() { return getTwoRegisters(DATA1LOW_REG); } float readLuxLevel() { unsigned int ch1Int = readCH1Level(); unsigned int ch0Int = readCH0Level(); float ch0 = (float)readCH0Level(); float ch1 = (float)readCH1Level(); switch (getIntegrationTime()) { case INT_TIME_13_7_MS: if ((ch1Int >= 5047) || (ch0Int >= 5047)) { return 1.0/0.0; } break; case INT_TIME_101_MS: if ((ch1Int >= 37177) || (ch0Int >= 37177)) { return 1.0/0.0; } break; case INT_TIME_402_MS: if ((ch1Int >= 65535) || (ch0Int >= 65535)) { return 1.0/0.0; } break; } float ratio = ch1/ch0; switch (getIntegrationTime()) { case INT_TIME_13_7_MS: ch0 *= 1/0.034; ch1 *= 1/0.034; break; case INT_TIME_101_MS: ch0 *= 1/0.252; ch1 *= 1/0.252; break; case INT_TIME_402_MS: ch0 *= 1; ch1 *= 1; break; } if (getGain() == LOW_GAIN) { ch0 *= 16; ch1 *= 16; } float luxVal = 0.0; if (ratio <= 0.5) { luxVal = (0.0304 * ch0) - ((0.062 * ch0) * (pow((ch1/ch0), 1.4))); } else if (ratio <= 0.61) { luxVal = (0.0224 * ch0) - (0.031 * ch1); } else if (ratio <= 0.8) { luxVal = (0.0128 * ch0) - (0.0153 * ch1); } else if (ratio <= 1.3) { luxVal = (0.00146 * ch0) - (0.00112*ch1); } return luxVal; return 0; } uint16_t getTwoRegisters(uint8_t regAddress) { Wire.beginTransmission(address); Wire.write(0x20 | regAddress); Wire.endTransmission(false); Wire.requestFrom(address, (uint8_t)2); uint16_t regVal = Wire.read(); return regVal | (Wire.read()<<8); }на самом деле буду пытаться , но если нет то нет
Понятно.
Попробую ещё раз намекнуть... Вызвав в самом начале, в строке 33 функцию begin, Вы быстренько попадёте в функцию setRegister. Сами проследите как. Теперь вопрос - строка 89 - чему равна переменная address? Ответ - она равна нулю. Ничего другого Вы ей нигде не присвоили. То же самое касается getRegister. Если бы Вы проверяли значения, возвращаемые Вашими функциями, то ошибка всплыла бы на стадии инициализации устройства.
Spasibo
Доброго времени суток, если не затруднит объясните почему в строке 215 при присвоении switchPointer = current_menu; выпадает ошибка о несовместимости типов
(sketch_aug14a.ino:215:22: error: invalid conversion from 'unsigned char' to 'switchVariants' [-fpermissive] Ошибка компиляции.)
#include <LiquidCrystal.h> LiquidCrystal lcd(7, 6, 5, 4, 3, 2); #include <avr/io.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #include <util/delay.h> //настройка параметров работы функций #define BTN_LOCK_TIME 30 /*время обработки дребезга в милисекундах (10-100)*/ #define BTN_LONG_TIME 1000 /*время фиксации длинного нажатия в милисекундах (1000 - 2500)*/ //настройки портов #define BTN_PORT PORTB /*порт чтения кнопок*/ #define BTN_DDR DDRB #define BTN_PIN PINB #define BTN_LINE_DN (1<<0) /*пины чтения кнопок*/ #define BTN_LINE_UP (1<<1) #define BTN_LINE_OK (1<<2) #define BTN_LINE_LEFT (1<<3) #define BTN_LINE_RIGHT (1<<4) #define BTN_LINE_CANSEL (1<<5) //глобальные переменные volatile uint8_t BtnFlags; //байт флагов нажатия кнопки #define BTN_SHRT_DN (1<<0) /*бит короткого нажатия кнопки up*/ #define BTN_SHRT_UP (1<<1) /*бит короткого нажатия кнопки dn*/ #define BTN_SHRT_OK (1<<2) /*бит короткого нажатия кнопки up*/ #define BTN_SHRT_LEFT (1<<3) /*бит короткого нажатия кнопки left*/ #define BTN_SHRT_RIGHT (1<<4) /*бит короткого нажатия кнопки right*/ #define BTN_SHRT_CANSEL (1<<5) /*бит короткого нажатия кнопки right*/ //####################################################################################################################### uint8_t buttonCount = 0; // счетчик нажатий кнопки unsigned char current_menu=0; //Переменная указывает на текущее меню unsigned char current_poz=0; //Переменная указывает на текущий Punkt меню/подменю char last_item; unsigned char f; //####################################################################################################################### //------------------------------------------ typedef void (*FuncPtr)(void); //указатель на функции FuncPtr FPtr; //Структура описывает текущее состояние меню и подменю struct Menu_State{ uint8_t menu;//1,2,3,4 uint8_t submenu;//1,2,3 }MN; typedef struct _selection { unsigned char ent_f : 4; //Флаг входа 4 бита — обычно ID меню в которое надо войти unsigned char esc_f : 4; //Флаг выхода 4 бита — обычно ID меню в которое надо вернуться }SELECTION; typedef struct _menu { //unsigned char id; //Номер меню/подменю //unsigned char num_selections; //Количество Punktов данного меню/подменю SELECTION *m; //Указатель намассив пунктов данного меню/подменю } PAGE_MENU; enum switchVariants : byte { // Определения для переключателя пунктов меню; MAIN_MENU, MENU_MANUAL, MENU_AUTO, MENU_SETUP, MENU_DEBUG//, EXITSAVE }; switchVariants switchPointer = MAIN_MENU; // С чего начнем цикл; enum manuState : byte { // Определения для переключателя ручного режима; EDIT_PARAM, HEAT_ZONE, COOL_ZONE, STOP_PROCESS, EXIT_PROCESS }; manuState mode = EDIT_PARAM; // С чего начнем цикл; static SELECTION menu_m0[]={ {MENU_MANUAL , MAIN_MENU},// изд 521(1) }; static SELECTION menu_m1[]={ {MENU_AUTO, MAIN_MENU}, //Punkt 2 }; static SELECTION menu_m2[]={ {MENU_SETUP, MAIN_MENU} //Punkt 1 }; static SELECTION menu_m3[]={ {MENU_DEBUG, MAIN_MENU} }; static PAGE_MENU menu[] = { menu_m0, //Меню 1 menu_m1, //Меню 2 menu_m2, //Меню 3 menu_m3 //Меню 4 }; const uint8_t MN000[] PROGMEM="REWORK v05\0"; //меню 1 const uint8_t MN100[] PROGMEM="SETTINGS\0"; //подпункт меню const uint8_t MN101[] PROGMEM="STEPS:\0"; const uint8_t MN102[] PROGMEM="DWELL:\0"; const uint8_t MN103[] PROGMEM="PWR:\0"; const uint8_t MN104[] PROGMEM="RAMP:\0"; const uint8_t MN105[] PROGMEM="TARGET:\0"; //меню 2 const uint8_t MN200[] PROGMEM="All\0"; //подпункт меню 2 const uint8_t MN201[] PROGMEM="ON\0"; const uint8_t MN202[] PROGMEM="OFF\0"; //меню 3 const uint8_t MN300[] PROGMEM="Auto\0"; //подпункт меню 3 const uint8_t MN301[] PROGMEM="Left\0"; //меню 4 const uint8_t MN400[] PROGMEM="Blink\0"; //подпункт меню 4 const uint8_t MN401[] PROGMEM="Fast\0"; //Массивы указателей на строки меню, хранящиеся на флэш const uint8_t *MENU[] ={ MN100, //menu 1 string MN200, //menu 2 string MN300, //menu 3 string MN400 //menu 4 string }; const uint8_t *SUBMENU[] ={ MN101, MN102, MN103, MN104, MN105, //подпункты меню 1 MN201, MN202, //подпункты меню 2 MN301, //подпункты меню 3 MN401, //подпункты меню 4 }; //Структура меню //[0] -Number of level 0 menu items //[1]...[n] number of second level menu items //Eg. MSTR2[1] shows that menu item 1 has 3 submenus const uint8_t MSTR2[] PROGMEM ={ 4, // количество пунктов меню 5, //Количество подпунктов в пункте меню 1 2, //Количество подпунктов в пункте меню 2 1, //Количество подпунктов в пункте меню 3 1 //Количество подпунктов в пункте меню 4 }; //Прототипы функций //Инициализация Timer2 void init_timer2(void); //Начальное меню void menu_Init(void); //Назначаем порты для кнопок и светодиодов void ports_Init(void); //Функции для каждого пункта меню void func101(void); void func102(void); void func103(void); void func104(void); void func105(void); void func201(void); void func202(void); void func301(void); void func401(void); //#define NULL_FUNC (void*)0 //Массив указателей на функции во флэш const FuncPtr FuncPtrTable[] PROGMEM= { func101, func102, func103, func104, func105, //functions for submenus of menu 1 func201, func202, //functions for submenus of menu 2 func301, //functions for submenus of menu 3 func401 //functions for submenus of menu 4 }; //SubMenu and Function table pointer update uint8_t MFIndex(uint8_t, uint8_t); //------------------------------------------ uint8_t pageNum = 0; // счетчик нажатий кнопки ISR(TIMER2_COMPA_vect) { BtnExe(); } //####################################################################################################################### void setup() { //Serial.begin(9600); lcd.begin(20, 4); lcd.home(); //Приветствие CopyStringtoLCD(MN000, 3, 1); _delay_ms(100); lcd.clear(); //Настройка таймера 2 ports_Init(); init_timer2(); // каждые 100 Гц sei(); // разрешаем прерывания глобально interrupts(); } void loop() { char BtnMask = BtnGet(); /* lcd.clear(); //Display menu item CopyStringtoLCD(MENU[MN.menu-1], 0, 0 ); //Display submenu item CopyStringtoLCD(SUBMENU[MFIndex(MN.menu, MN.submenu)], 0, 1 ); //Assign function to function pointer FPtr=(FuncPtr)pgm_read_word(&FuncPtrTable[MFIndex(MN.menu, MN.submenu)]); */ if (BtnMask == BTN_SHRT_OK) { current_menu=menu[buttonCount].m[0].ent_f; switchPointer = current_menu; }//обработка короткого нажатия ВВЕРХ if (BtnMask == BTN_SHRT_CANSEL) { }//обработка короткого нажатия ВЛЕВО switch (switchPointer) // Все делаем в одном операторе и одной функции; { case MAIN_MENU: /***************** Главное меню ***************/ startMenu(); //формирование меню if (BtnMask == BTN_SHRT_UP) { }//обработка короткого нажатия ВВЕРХ if (BtnMask == BTN_SHRT_DN) { }//обработка короткого нажатия ВНИЗ if (BtnMask == BTN_SHRT_RIGHT) //обработка короткого нажатия ВПРАВО { buttonCount++; // с каждым нажатием buttonCount++ пока buttonCount<4 if (buttonCount > 3) buttonCount = 0; } if (BtnMask == BTN_SHRT_LEFT) { }//обработка короткого нажатия ВЛЕВО break; case MENU_MANUAL: /***************** Ручной режим ***************/ switch (mode) { // Выбор режима работы ручного режима case EDIT_PARAM: // Режим редактирования break; case HEAT_ZONE: break; case COOL_ZONE: break; case STOP_PROCESS: break; } break; case MENU_AUTO: /***************** Автоматический режим ***************/ break; case MENU_SETUP: /***************** Настройки ***************/ break; case MENU_DEBUG: /***************** Настройки ***************/ break; } } //####################################################################################################################### //----------------------------------------------------------------------------------------------------------------------- //функция настройки библиотеки работы с кнопками void ports_Init(void) { BTN_DDR &= ~(BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_OK| BTN_LINE_LEFT| BTN_LINE_RIGHT| BTN_LINE_CANSEL); // кнопки на ввод BTN_PORT |= (BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_OK| BTN_LINE_LEFT| BTN_LINE_RIGHT| BTN_LINE_CANSEL); //подтяжка вкл } //----------------------------------------------------------------------------------------------------------------------- static void init_timer2(void) { TCCR2B=0; // таймер2 остановлен TCNT2=0; //счётный регистр обнулён OCR2B=0; TIFR2&=0xff; //отчистить флаги прерываний TCCR2A = (1<<WGM21); // Режим CTC (сброс по совпадению) TCCR2B = (1<<CS20)|(1<<CS21)|(1<<CS22); // CLK/1024 OCR2A = 155; TIMSK2 = (1<<OCIE2A); // Разрешить прерывание по совпадению } //----------------------------------------------------------------------------------------------------------------------- //функция чтения данных о нажатии кнопок char BtnGet (void) { cli(); char temp = BtnFlags; BtnFlags = 0; sei(); return temp; } //----------------------------------------------------------------------------------------------------------------------- //ФУНКЦИЯ ОБРАБОТКИ НАЖАТИЙ КЛАВИШ (вызывать в прерывании с частотой 100 Гц) //короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags //длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags void BtnExe (void) { static unsigned char BtnLockBit = 0; //защелка (защита от дребезга) static unsigned char BtnLockCount = 0; //счетчик защелки (защита от дребезга) static unsigned char BtnLongCount = 0; //счетчик длинного нажатия static unsigned char BtnLastState= 0; //последнее состояние кнопок перед отпусканием char mask = 0; if (! (BTN_PIN & BTN_LINE_DN)) mask = BTN_SHRT_DN; if (! (BTN_PIN & BTN_LINE_UP)) mask = BTN_SHRT_UP; if (! (BTN_PIN & BTN_LINE_OK)) mask = BTN_SHRT_OK; if (! (BTN_PIN & BTN_LINE_LEFT)) mask = BTN_SHRT_LEFT; if (! (BTN_PIN & BTN_LINE_RIGHT)) mask = BTN_SHRT_RIGHT; if (! (BTN_PIN & BTN_LINE_CANSEL)) mask = BTN_SHRT_CANSEL; if (mask){ //опрос состояния кнопки if (BtnLockCount < (BTN_LOCK_TIME/10)){ //клавиша нажата BtnLockCount++; return; //защелка еще не дощитала - возврат } BtnLastState = mask; BtnLockBit =1; //нажатие зафиксировано //if (BtnLongCount >= (BTN_LONG_TIME/10)) // return; //возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше //if (++BtnLongCount >= (BTN_LONG_TIME/10)) // BtnFlags |= (BtnLastState<<4); //счетчик досчитал до максимума - устанавливаем биты длинного нажатия } else{ //клавиша отжата if (BtnLockCount){ BtnLockCount --; return; //защелка еще не обнулилась - возврат } if (! BtnLockBit) //СТАТИЧЕСКИЙ ВОЗВРАТ return; BtnLockBit =0; //отжатие зафиксировано if (BtnLongCount < (BTN_LONG_TIME/10)) BtnFlags |= BtnLastState; //установка бита короткого нажатия //BtnLongCount = 0; //сброс счетчика длительности нажатия } } void CopyStringtoLCD(const uint8_t *FlashLoc, uint8_t x, uint8_t y) { uint8_t i; lcd.setCursor(x,y); for(i=0;(uint8_t)pgm_read_byte(&FlashLoc[i]);i++) { lcd.write((uint8_t)pgm_read_byte(&FlashLoc[i])); } } //------------------------------------------ void menu_Init(void) { MN.menu=1;//MN.menu=buttonCount+1; MN.submenu=1; lcd.clear(); CopyStringtoLCD(MENU[(MN.menu-1)], 0, 0 ); CopyStringtoLCD(SUBMENU[(MN.submenu-1)], 0, 1 ); //FPtr=(FuncPtr)pgm_read_word(&FuncPtrTable[0]); } //------------------------------------------ uint8_t MFIndex(uint8_t mn, uint8_t sb) { uint8_t p=0;//points to menu in table of function pointer for(uint8_t i=0; i<(mn-1); i++) { p=p+pgm_read_byte(&MSTR2[i+1]); } p=p+sb-1; return p; } //------------------------------------------ void func101(void) { } void func102(void) { } void func103(void) { } void func104(void) { } void func105(void) { } void func201(void) { } void func202(void) { } void func301(void) { } void func302(void) { } void func401(void) { } void func402(void) { } void setString(unsigned char *bcount) { static uint8_t pos_y_curs = 4; lcd.setCursor(0, *bcount); lcd.write(62); if (bcount == 0) *bcount = pos_y_curs; lcd.setCursor(0, *bcount - 1); lcd.write(32); } void startMenu(){ setString(&buttonCount); // включаем отображение стрелки выбора меню lcd.setCursor(1, 0); // 1 строка lcd.print(F("PY HO ")); // ручной режим lcd.setCursor(1, 1); // 2 строка lcd.print(F("ABTOMAT ECK")); // автоматический режим lcd.setCursor(1, 2); // 3 строка lcd.print(F("HACTPO K ")); // настройки lcd.setCursor(1, 3); // 4 строка lcd.print(F("OT A KA")); // отладка }потому что пытаетесь типу switchVariants присвоить unsigned char
я не смотрел внимательно может поможет
да и init_timer2 объявлена как void, а реализация как static void, думаю тоже ругнется.
Спасибо, помогло. Насчет static void забыл убрать когда переносил код, буду внимательнее