// #include // #include // #define SLAVE_ADDRESS 9 // адрес устройства slave // #define COMMAND_1 0x01 //команда включения шим // #define COMMAND_2 0x02 //команда выключения шим // #define COMMAND_3 0x03 //команда изменения частоты шим // #define COMMAND_4 0x04 //команда изменения скважности шим // #define COMMAND_5 0x05 //команда изменения скважности шим // uint16_t frequency = 1 << 4; // uint8_t dutycycle = 50; // uint8_t buffer[32]; // буфер для полученных данных // uint8_t cnt = 0; // счетчик байтов // bool tran_end = false; //флаг окончания передачи // void i2c_init() { // TWAR = SLAVE_ADDRESS << 1; // задаем адрес устройства // TWSR = 0; // частота шины 100 кГц (скорость передачи) // TWCR = (1 << TWEN) | (1 << TWEA) | (1 << TWIE); // включаем slave reciever // } // // обработчик прерывания TWI // ISR(TWI_vect) { // switch (TWSR) { // case 0x60: // SLA+W received, ACK returned // //cnt = 0; // сброс счетчика // //tran_end = false; // TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA) | (1 << TWIE); // включаем прерывание и устанавливаем бит ACK // break; // case 0x80: // data byte received, ACK returned // buffer[cnt++] = TWDR; // сохраняем принятые данные // TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA) | (1 << TWIE); // break; // case 0x88: // last data byte received, NACK returned // buffer[cnt++] = TWDR; // сохраняем последний байт данных // TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA) | (1 << TWIE); // break; // case 0xA0: // STOP or repeated START received // tran_end = true; // TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA) | (1 << TWIE); // break; // default: // TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA) | (1 << TWIE); // break; // } // } // void timer1_init() { // PORTB = 0; // DDRB |= (1 << PORTB1); //OC1A // DDRB |= (1 << PORTB2); //OC1B // TCCR1A = 0; // обнуляем регистры управления // TCCR1B = 0; // TCNT1 = 0; // и счетный регистр // } // //частота приходит в 16 раз больше // void timer1_on(uint16_t frequency, uint8_t dutycycle) { // // Неинверсный режим работы // TCCR1A |= (0 << COM1A1) | (0 << COM1A0) | (1 << COM1B1) | (0 << COM1B0); // //Fast PWM (Быстрый ШИМ) // TCCR1A |= (1 << WGM11) | (1 << WGM10); // TCCR1B |= (1 << WGM13) | (1 << WGM12); // //Предделитель - 1024 // TCCR1B |= (1 << CS12) | (0 << CS11) | (1 << CS10); // //Частота // OCR1A = F_CPU / 1024 * 16 / frequency; // //Скважность // OCR1B = (F_CPU / 1024 * 16 / frequency) * dutycycle / 100; // } // void timer1_off() { // // TCCR1A &= ~((1 << COM1A1) | (1 << COM1A0)); // //Fast PWM (Быстрый ШИМ) // TCCR1A |= (0 << WGM11) | (0 << WGM10); // TCCR1B |= (0 << WGM13) | (0 << WGM12); // TCCR1A |= (0 << COM1A1) | (0 << COM1A0) | (0 << COM1B1) | (0 << COM1B0); //шим отключен, нормальная работа порта // TCCR1B = 0; // // OCR1A = 0; // // OCR1B = 0; // } // void setup(void) { // i2c_init(); //инициализация i2c // timer1_init(); // Serial.begin(9600); // Serial.println("PWM Slave started!"); // sei(); // включаем прерывания // } // void loop() { // if (tran_end) { // tran_end = false; // for(int i = 0;i<100;i++){ // } // if (buffer[0] == COMMAND_1) { // Serial.print("cmd: 0x"); // Serial.println(buffer[0]); // timer1_on(frequency, dutycycle); // Serial.print(", data bytes: "); // Serial.print(buffer[1], HEX); // Serial.print(" "); // Serial.println(buffer[2], HEX); // Включение ШИМ // } else if (buffer[0] == COMMAND_2) { // Serial.print("cmd: 0x"); // Serial.println(buffer[0]); // timer1_off(); // Serial.print(", data bytes: "); // Serial.print(buffer[1], HEX); // Serial.print(" "); // Serial.println(buffer[2], HEX); // Выключение ШИМ // } else if (buffer[0] == COMMAND_3) { // Serial.print("cmd: 0x"); // Serial.println(buffer[0]); // frequency = (buffer[1] << 8) + buffer[2]; // Serial.print("frequency value: "); // Serial.print(frequency); // Serial.print(", data bytes: "); // Serial.print(buffer[1], HEX); // Serial.print(" "); // Serial.println(buffer[2], HEX); // } else if (buffer[0] == COMMAND_4) { // Serial.print("cmd: 0x"); // Serial.println(buffer[0]); // frequency = (buffer[1] << 8) + buffer[2]; // Serial.print("frequency value: "); // Serial.print(frequency); // Serial.print(", data bytes: "); // Serial.print(buffer[1], HEX); // Serial.print(" "); // Serial.println(buffer[2], HEX); // } else if (buffer[0] == COMMAND_5) { // Serial.print("cmd: 0x"); // Serial.println(buffer[0]); // dutycycle = buffer[1]; // Serial.print("dytycycle value: "); // Serial.println(dutycycle); // Serial.print(", data bytes: "); // Serial.print(buffer[1], HEX); // Serial.print(" "); // Serial.println(buffer[2], HEX); // } else if (buffer[0] == COMMAND_5) { // Serial.print("cmd: 0x"); // Serial.println(buffer[0]); // dutycycle = buffer[1]; // Serial.print("dytycycle value: "); // Serial.println(dutycycle); // Serial.print(", data bytes: "); // Serial.print(buffer[1], HEX); // Serial.print(" "); // Serial.println(buffer[2], HEX); // } // cnt = 0; // } // } #include #include #define SLAVE_ADDRESS 9 // адрес устройства slave #define COMMAND_1 0x01 //команда включения шим #define COMMAND_2 0x02 //команда выключения шим #define COMMAND_3 0x03 //команда изменения частоты шим #define COMMAND_4 0x04 //команда изменения скважности шим #define COMMAND_5 0x05 //команда изменения скважности шим #define COMMAND_6 0x06 //команда изменения скважности шим uint16_t frequency = 1 << 4; uint8_t dutycycle = 50; uint8_t buffer[32]; // буфер для полученных данных uint8_t cnt = 0; // счетчик байтов bool tran_end = false; //флаг окончания передачи void i2c_init() { TWAR = SLAVE_ADDRESS << 1; // задаем адрес устройства TWSR = 0; // частота шины 100 кГц (скорость передачи) TWCR = (1 << TWEN) | (1 << TWEA) | (1 << TWIE); // включаем slave reciever } // обработчик прерывания TWI ISR(TWI_vect) { switch (TWSR) { case 0x60: // SLA+W received, ACK returned //cnt = 0; // сброс счетчика //tran_end = false; TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA) | (1 << TWIE); // включаем прерывание и устанавливаем бит ACK break; case 0x80: // data byte received, ACK returned buffer[cnt++] = TWDR; // сохраняем принятые данные TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA) | (1 << TWIE); break; case 0x88: // last data byte received, NACK returned buffer[cnt++] = TWDR; // сохраняем последний байт данных TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA) | (1 << TWIE); break; case 0xA0: // STOP or repeated START received tran_end = true; TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA) | (1 << TWIE); break; default: TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA) | (1 << TWIE); break; } } void timer1_init() { PORTB = 0; DDRB |= (1 << PORTB1); //OC1A DDRB |= (1 << PORTB2); //OC1B TCCR1A = 0; // обнуляем регистры управления TCCR1B = 0; TCNT1 = 0; // и счетный регистр } //частота приходит в 16 раз больше void timer1_on(uint16_t frequency, uint8_t dutycycle) { // Неинверсный режим работы TCCR1A |= (0 << COM1A1) | (0 << COM1A0) | (1 << COM1B1) | (0 << COM1B0); //Fast PWM (Быстрый ШИМ) TCCR1A |= (1 << WGM11) | (1 << WGM10); TCCR1B |= (1 << WGM13) | (1 << WGM12); //Предделитель - 1024 TCCR1B |= (1 << CS12) | (0 << CS11) | (1 << CS10); //Частота OCR1A = F_CPU / 1024 * 16 / frequency; //Скважность OCR1B = (F_CPU / 1024 * 16 / frequency) * dutycycle / 100; } void timer1_off() { // TCCR1A &= ~((1 << COM1A1) | (1 << COM1A0)); //Fast PWM (Быстрый ШИМ) TCCR1A |= (0 << WGM11) | (0 << WGM10); TCCR1B |= (0 << WGM13) | (0 << WGM12); TCCR1A |= (0 << COM1A1) | (0 << COM1A0) | (0 << COM1B1) | (0 << COM1B0); //шим отключен, нормальная работа порта TCCR1B = 0; // OCR1A = 0; // OCR1B = 0; } void setup(void) { i2c_init(); //инициализация i2c timer1_init(); Serial.begin(9600); Serial.println("PWM Slave started!"); sei(); // включаем прерывания } void loop() { if (tran_end) { tran_end = false; Serial.println(" "); for (int i = 0; i < cnt; i++) { Serial.print(buffer[i], HEX); // вывод байтов в шестнадцатеричном формате Serial.print(" "); } if (buffer[0] == COMMAND_1) { timer1_on(frequency, dutycycle); } else if (buffer[0] == COMMAND_2) { timer1_off(); } else if (buffer[0] == COMMAND_3) { frequency = (buffer[1] << 8) + buffer[2]; } else if (buffer[0] == COMMAND_4) { frequency = (buffer[1] << 8) + buffer[2]; } else if (buffer[0] == COMMAND_5) { dutycycle = buffer[1]; } else if (buffer[0] == COMMAND_6) { dutycycle = buffer[1]; } cnt = 0; } }