Ви не увійшли.
Или сделайте тип:
typedef struct {
boolean on;
boolean longpress;
} BUTTON;
Или пишите везде struct BUTTON
“Button” does not name a type
В подпрограмме обработки нажатия кнопок выдает ошибку (
Что не так?
#include <mcp_can_dfs.h>
#include <mcp_can.h>
#include <SPI.h>
#include <EEPROM.h>
#include <avr/sleep.h>
#include <avr/power.h>
// Красный провод – Vcc c +5 В, белый — RXD, зелёный – TXD, чёрный – GN
#define PinTX 0
#define PinRX 1
#define PinSDA 2
#define PinSCL 3
#define LED_Steer_Pin 8 // Пин контрольного светодиода руля (сине-черный)
#define freePin0 5
#define freePin1 6
#define serviceCanPin 7
#define LED_Glass_Pin 4 // Пин контрольного светодиода стекла (бело-зеленый)
#define freePin2 9
#define DebugPin 10
#define Button_Glass_Pin 11 // Пин кнопкм стекла (черно-белый)
#define Button_Steer_Pin 12 // Пин кнопки руля (сине-зеленый)
#define FreePin4 21
#define MCP_PORT 10
#define LedOnBoard 23
#define IRN_SDA 1 // Прерывание для кнопки стекла
#define IRN_SCL 0 // Прерывание для кнопки руля
#define IRN_UART_RX 2 // Прерывание для Serial1. Не используется. Поставлено для порядка )).
#define IRN_UART_TX 3 // Прерывание для Serial1. Используется для просыпания в режиме сна.
#define IRN_CAN 4 // Прерывание для CAN. Только для Leonardo Can Bus
#define PrintPort Serial1
#define PrintBaud 115200
#define TimeInactivityMAX 20000 // Максимально допустимое кол-во миллисекунд неактивности шины перед переходом в сон.
#define CanIDClimate 0x601 // Порт СAN шины для управления обогревом
#define CAN_ID_time 0x6B6 // Порт СAN шины для отслеживания времени
#define carModeSleep 0 // Режимы работы: все спят
#define carModeWake 1 // Сняли с сигналки
#define carModeACC 2 // Зажигание
#define carmodeEngine 3 // Мотор работает
const int EE_Steer_Address = 0; // Адрес постоянного хранилища состояния обогрева руля
const int EE_Glass_Address = 1; // Адрес постоянного хранилища состояния обогрева стекла
boolean EE_Steer = false; // Состояние руля true - вкл, false - выкл
boolean EE_Glass = false; // Состояния стекла true - вкл, false - выкл
byte ADCSRA_OLD_SAVED;
MCP_CAN CAN(MCP_PORT); // Инициализация порта CAN шины
unsigned char SteerOff[5] = {0x20, 0x74, 0x00, 0x00, 0x00}; // КАН строка выключение руля
unsigned char SteerOn [5] = {0x20, 0x74, 0x00, 0x01, 0x00}; // КАН строка включение руля
unsigned char GlassOff[4] = {0x20, 0x6D, 0x00, 0x01}; // КАН строка выключение стекла
unsigned char GlassOn [4] = {0x20, 0x6D, 0x01, 0x01}; // КАН строка включение стекла
unsigned char len = 0; // Длина полученной строки
unsigned char buf[8]; // Буфер КАН шины
long timeLastCan = 0; // Время последнего обращения к шине
volatile boolean flagRecv = false; // Флаг того, что сработало прерывание - получен сигнал по CAN шине.
volatile boolean flagAwake = false;
volatile boolean flagSleep = false; // Уснули
volatile boolean flagled = false;
volatile boolean flagNoDebug = true;
volatile int carMode =
struct BUTTON { // структура кнопка
boolean on; // нажатие было
boolean longpress; // нажатие было длинным
};
void setup() {
PrintPort.begin(115200); // Инициализация ком порта для контрольного вывода. В будущем, все строки Serial можно закомментировать
while(!PrintPort) {
delay(50);
}
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // Инициализация КАН шины : baudrate = 500k
PrintPort.println("CAN BUS Shield init fail");
PrintPort.println(" Init CAN BUS Shield again");
delay(100);
}
ADCSRA_OLD_SAVED = ADCSRA;
ADCSRA= 0; // Выключение АЦП
pinMode(Button_Glass_Pin,INPUT_PULLUP); // Инициализация кнопки стекла
pinMode(Button_Steer_Pin,INPUT_PULLUP); // Инициализация кнопки руля
pinMode(PinSDA, INPUT_PULLUP); // порт под отладочное прерывание- вывод из сна
pinMode(LedOnBoard, OUTPUT);
pinMode(LED_Glass_Pin, OUTPUT);
pinMode(LED_Steer_Pin, OUTPUT);
digitalWrite(LedOnBoard, HIGH);
pinMode(DebugPin, INPUT_PULLUP);
flagNoDebug = (digitalRead(DebugPin)== HIGH);
if (!flagNoDebug) PrintPort.println ("Debug mode");
pinMode(DebugPin, OUTPUT);
digitalWrite(DebugPin, LOW);
EE_Steer = EEPROM.read(EE_Steer_Address); // Чтение из памяти состояние руля
EE_Glass = EEPROM.read(EE_Glass_Address); // Чтение из памяти состояние стекла
attachInterrupt(4, ISR_CAN, FALLING); // Инициализация прерывания по чтению из КАН шины
pinMode(PinSDA, INPUT_PULLUP);
attachInterrupt (1, ISR_AWAKE, FALLING); // отдадочное прерывание
CAN.init_Mask(0, 0, 0x7FF) ; // there are 2 mask in mcp2515, you need to set both of them
CAN.init_Mask(1, 0, 0x7FF); // в оригинале стоит 0x3FF ?
CAN.init_Filt(0, 0, CanIDClimate); // маска порта, отвечающего за климат
CAN.init_Filt(1, 0, CAN_ID_time); // вторая маска - порт времени
timeLastCan = millis();
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Здесь устанавливается режим сна
PrintPort.println("**************************************");
Steer (); // Инициализация обогревов из памяти
Glass ();
PrintPort.println("* Setup OK . ver. 06-11 21: *");
PrintPort.println("**************************************");
}
void Glass() { // Подпрограмма управление стеклом
if (EE_Glass) { // Если флаг стекла установлен
CAN.sendMsgBuf(CanIDClimate, 0, 4, GlassOn); // Посылка команды включение обогрева стекла
digitalWrite(LED_Glass_Pin,HIGH); // Включение светодиода стекла
PrintPort.println(" Glass On");
}
else { // Иначе - флаг обогрева сброшен
CAN.sendMsgBuf(CanIDClimate, 0, 4, GlassOff); // Посылка команды выключение обогрева стекла
digitalWrite(LED_Glass_Pin,LOW); // Выключение светодиода стекла
PrintPort.println(" Glass off");
}
delay(200);
}
void ISR_CAN() { // Обработка прерывания шины.
sleep_disable();
flagRecv = true;
}
void ISR_AWAKE() {
sleep_disable();
flagAwake = true;
}
boolean timetoSleep() { // Проверка того не пора ли ложиться спать
int time = millis() - timeLastCan; // сколько времени прошло с тех пор, как что то получали
if (time<0) timeLastCan = millis(); // Если было переполнение времени - обновляем счетчик времени
return (time > TimeInactivityMAX)&&flagNoDebug; // Если давно не получали ничего по шине то надо спать и нет отладки
}
void sleepNow() { // функциия ухода в спячку(
PrintPort.println("Sleep mode "); // отладка
digitalWrite(LED_Glass_Pin,LOW); // Выключение светодиода руля
digitalWrite(LED_Steer_Pin,LOW); // Выключение светодиода стекла
digitalWrite(LedOnBoard, LOW);
flagSleep = true;
USBDevice.detach(); // Выключаем USB
delay(50);
/* pinMode(Button_Glass_Pin, OUTPUT);
pinMode(Button_Steer_Pin, OUTPUT);
digitalWrite(Button_Glass_Pin, LOW);
digitalWrite(Button_Steer_Pin, LOW);
*/
delay(100); // Этот делэй необходим, чтоб функция sleep не вызывала ошибку по Serial
sleep_enable(); // Включаем sleep-бит в регистре mcucr. Теперь возможен слип
sleep_mode(); // Здесь устройство перейдет в режим сна!!!
// -----------------------------------------------ПОСЛЕ ПРОСЫПАНИЯ ВЫПОЛНЕНИЕ КОДА ПРОДОЛЖИТСЯ ОТСЮДА!!! ????
}
void wakeNow() { // Просыпаемся из спящего режима
USBDevice.attach(); // Выключаем USB
digitalWrite(LedOnBoard, HIGH); // Зажигаем обратно светодиод
// pinMode(Button_Glass_Pin, INPUT_PULLUP);
// pinMode(Button_Steer_Pin, INPUT_PULLUP);
delay(100);
flagSleep = false; // Выключаем спящий статус
Steer();
Glass();
timeLastCan = millis(); // Время последнего полученного сообщенияо шине.
PrintPort.println("Awake");
flagAwake = false; // Проснулись полностью, флаг прячем
}
void Steer() { // Подпрограмма управление рулем
if (EE_Steer) // Если флаг обогрева установлен
{
CAN.sendMsgBuf(CanIDClimate, 0, 5, SteerOn); // Посылка команды включения обогрева руля
digitalWrite(LED_Steer_Pin,HIGH); // Включение светодиода руля
PrintPort.println(" Steer on");
}
else // Иначе - флаг обогрева сброшен
{
CAN.sendMsgBuf(CanIDClimate, 0, 5, SteerOff); // Посылка команды вкылючения обогрева руля
digitalWrite(LED_Steer_Pin,LOW); // Выключение светодиода руля
PrintPort.println(" Steer off");
}
delay(200);
}
void Blink(int pin, int n, boolean led) // Подпрограмма "Моргание светодиодом в подтверждение". Номер пина, количество морганий, статус в котором надо оставить.
{
if (led) // если светодиод уже горит, то выключаем
{
digitalWrite(pin,LOW);
delay (500);
}
for (int i=0; i<n; i++)
{ // n раз моргнули в подтверждение
digitalWrite(pin,HIGH);
delay (500);
digitalWrite(pin,LOW);
delay (500);
}
if (led) digitalWrite(pin,HIGH); // Включили светодиод обратно, если надо.
}
ВОТ ЗДЕСЬ ВЫДАЕТ ОШИБКУ BUTTON Pressing(int pin) [/color][/s] // Подпрограмма обработка нажатия кнопки. Pin - номер порта
{
int n = 0; // Счетчик
BUTTON key; // Структура кнопки для возврата
while (digitalRead(pin)==LOW && n <=100) // Обрабатывет длинное нажатие, считает тайминги, выход, если превышен таймиг или кнопка отпущена
{
n++; // Увеличение счетчика тайминга
delay (20);
}
key.on = (n>0&& n<100); // Установлен флаг короткого нажатия
key.longpress = (n>=100); // Установлен флаг длинное нажатие
return key;
}
void KeyDetect() // Подпрограмма чтения кнопки
{
BUTTON glass = Pressing (Button_Glass_Pin); // Чтение нажатия кнопки стекла
BUTTON steer = Pressing (Button_Steer_Pin); // Чтение нажатия кнопки руля
if (steer.longpress) // ОБработка длинного нажатия кнопки руля
{
EEPROM.write (EE_Steer_Address,EE_Steer); // Запись текущего состояния в EEPROM
PrintPort.write("Steer to ROM");
Blink (LED_Steer_Pin, 5, EE_Steer); // Моргнуть 5 раз и оставить в том же положении, что был
delay (500);
}
if (glass.longpress) // ОБработка длинного нажатия кнопки стекла
{
EEPROM.write (EE_Glass_Address,EE_Glass); // Запись текущего состояния в EEPROM
PrintPort.write("Glass to ROM");
Blink (LED_Glass_Pin, 5, EE_Glass); // Моргнуть 5 раз и оставить в том же положении, что был
delay(500);
}
if (steer.on) // ОБработка простого нажатия кнопки руля
{
EE_Steer = !EE_Steer; // Меняем значение флага обогрева руля на противоположное
Steer (); // Отправляем на обработку с текушщим значением
}
if (glass.on) // ОБработка простого нажатия кнопки стекла
{
EE_Glass = !EE_Glass; // Обращаем значение обогрева стекла
Glass(); // Отправляем на обработку с текушщим значением
}
}
void readCAN() { // ОБработка перехвата внешнего воздействия через КАН шину
flagRecv=0;
timeLastCan = millis();
boolean steer_on = true, steer_off = true; // Инициализация ключей проверки строки
boolean glass_on = true, glass_off = true;
while (CAN_MSGAVAIL == CAN.checkReceive()) // Взято из примера, очищение буфера
{
CAN.readMsgBuf(&len, buf); // Чтение данных из буфера КАН. Данные - len: data length, buf: data buf
if ((len==5)&&(CAN.getCanId()==CanIDClimate)) { // Если длина строки == 5, то это руль
for(int i = 0; i<len; i++) {
steer_on = steer_on && (buf[i]==SteerOn [i]); // Сравниваем побитово на совпадение со сторокй включения руля
steer_off = steer_off && (buf[i]==SteerOff[i]); // Сравниваем побитово на совпадение со строкой выключения руля
}
if (steer_on) { // Если перехвачена команда включения руля
EE_Steer = true; // Установка флага -подогрев руля включен
digitalWrite(LED_Steer_Pin,HIGH); // Включение светодиода руля
PrintPort.println(" External steer on");
}
else if (steer_off) { // Если перехвачена команды выключения руля
EE_Steer = false; // Установка флага - подогрев руля выключен
digitalWrite(LED_Steer_Pin,LOW); // Выключение светодиода руля
PrintPort.println(" External steer off");
}
else PrintPort.println(" Steer unknown command");
}
else if ((len==4)&&(CAN.getCanId()==CanIDClimate)) { // Если длина строки == 4, ьо это стекло
for(int i = 0; i<len; i++) {
glass_on = glass_on && (buf[i]==GlassOn [i]); // Сравниваем побитово на совпадение со строкой включения стекла
glass_off = glass_off && (buf[i]==GlassOff[i]); // Сравниваем побитово на совпадение со строкой вылючения стекла
}
if (glass_on) { // Если перехвачена команда включения стекла
EE_Glass = true; // Установка флага включения стекла
digitalWrite(LED_Glass_Pin,HIGH); // Включение светодиода стекла
PrintPort.println(" External glass on");
}
else if (glass_off) { // Если перехвачена команда включения стекла
EE_Glass = false; // Установка флага выключения стекла
digitalWrite(LED_Glass_Pin,LOW); // Выключение светодиода стекла
PrintPort.println(" External glass off");
}
else PrintPort.println(" Glass unknown command");
} // Конец распознавания
} // Конец цикла чтения из буфера
}
void loop() { // Основной цикл
if (flagSleep && (flagAwake || flagRecv )) {
flagAwake = false;
flagRecv = false;
wakeNow(); // Если команда на просыпание
}
if (!flagSleep) {
if (flagRecv) readCAN(); // Что то получили по шине
if (timetoSleep()) sleepNow();
KeyDetect(); // ОБработка нажатия клавиши
}
}
/*********************************************************************************************************
END FILE
*********************************************************************************************************/