// // Created by FSB-PC on 23.06.2023. // // #include // void setup() { // Wire.begin(9); // Устанавливаем адрес слейва // Wire.onReceive(receiveEvent); // Указываем функцию для обработки приема данных // Serial.begin(9600); // } // void loop() { // // Здесь можно добавить другие действия слейва, если необходимо // } // void receiveEvent(int numBytes) { // while (Wire.available()) { // uint8_t cmd = Wire.read(); // uint8_t upper_byte = Wire.read(); // uint8_t lower_byte = Wire.read(); // uint16_t cmd_value = (upper_byte << 8) | lower_byte; // float value = cmd_value / 16.0; // Serial.print("Received command: 0x"); // Serial.print(cmd, HEX); // Serial.print(", value: "); // Serial.print(value); // Serial.print(", data bytes: 0x"); // Serial.print(upper_byte, HEX); // Serial.print(" "); // Serial.println(lower_byte, HEX); // } // } #include #include #define SLAVE_ADDRESS 9 // адрес устройства slave #define COMMAND_1 0x01 //команда включения шим #define COMMAND_2 0x02 //команда выключения шим #define COMMAND_3 0x03 //команда изменения частоты шим #define COMMAND_4 0x04 //команда изменения скважности шим 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 |= (0 << COM1A1) | (0 << COM1A0) | (0 << COM1B1) | (0 << COM1B0); //шим отключен, нормальная работа порта } 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; if (buffer[0] == COMMAND_1) { Serial.println(buffer[0]); timer1_on(frequency, dutycycle); // Включение ШИМ } else if (buffer[0] == COMMAND_2) { Serial.println(buffer[0]); timer1_off(); // Выключение ШИМ } else if (buffer[0] == COMMAND_3) { Serial.println(buffer[0]); frequency = (buffer[1] << 8) + buffer[2]; } else if (buffer[0] == COMMAND_4) { dutycycle = buffer[1]; } cnt = 0; } }