#include #include #include #define I2C_FREQ 100000UL #define F_CPU 16000000UL #define I2C_PRESCALER 1 #define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER) #define I2C_READ 1 #define I2C_WRITE 0 void i2c_init() { TWBR = I2C_BITRATE; } void i2c_start() { // отправляем START bit TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // ожидаем пока START bit будет успешно отправлен while (!(TWCR & (1 << TWINT))); } void i2c_stop() { // отправляем STOP bit TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); // ожидаем пока STOP bit будет успешно отправлен while (TWCR & (1 << TWSTO)); } void i2c_write(uint8_t address, const uint8_t* data, uint8_t length) { i2c_start(); // Отправляем адрес устройства с битом записи TWDR = address << 1 | I2C_WRITE; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); for (uint8_t i = 0; i < length; i++) { TWDR = data[i]; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); } i2c_stop(); } void i2c_read(uint8_t address, uint8_t* data, uint8_t length) { i2c_start(); // Отправляем адрес устройства с битом чтения TWDR = address << 1 | I2C_READ; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); for (uint8_t i = 0; i < length; i++) { // для всех байт, кроме последнего - отправляем ACK if (i < length - 1) { TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); while (!(TWCR & (1 << TWINT))); data[i] = TWDR; } // для последнего байта - отправляем NACK else { TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); data[i] = TWDR; } } i2c_stop(); } #define F_CPU 16000000UL void pwm_init() { TCCR1A |= (1 << COM1A1) | (1 << WGM11); // non-inverting mode, Fast PWM (mode 14) TCCR1B |= (1 << WGM12) | (1 << WGM13) | (1 << CS10); // Fast PWM (mode 14), prescaler = 1 DDRB |= (1 << PB1); // set pin PB1 as output } void pwm_set_frequency(uint16_t frequency) { uint16_t prescaler = 1; uint32_t top = F_CPU / (prescaler * frequency) - 1; ICR1 = top; } void pwm_set_duty_cycle(float dutyCycle) { uint16_t value = ICR1 * dutyCycle / 100.0; OCR1A = value; } void pwm_enable() { pwm_set_duty_cycle(50); // Начальная скважность } void pwm_disable() { pwm_set_duty_cycle(0); // Выключение ШИМ } void i2c_init(); void i2c_start(); void i2c_stop(); void i2c_write(uint8_t address, const uint8_t* data, uint8_t length); void i2c_read(uint8_t address, uint8_t* data, uint8_t length); void pwm_init(); void pwm_set_frequency(uint16_t frequency); void pwm_set_duty_cycle(float dutyCycle); void pwm_enable(); void pwm_disable(); const uint8_t BUTTON_PIN[] = {0, 1, 2, 3, 4, 5}; const uint8_t PWM_SLAVE_ADDR = 9; uint16_t command = 0x00; float frequency = 1000.0; float dutyCycle = 50.0; void setup() { i2c_init(); pwm_init(); pwm_enable(); // Включение ШИМ // Инициализируем пины кнопок DDRC &= ~(1 << PINC0) & ~(1 << PINC1) & ~(1 << PINC2) & ~(1 << PINC3) & ~(1 << PINC4) & ~(1 << PINC5); // подключены кнопки на пинах А0, А1, А2, А3, А4, А5 PORTC |= (1 << PINC0) | (1 << PINC1) | (1 << PINC2) | (1 << PINC3) | (1 << PINC4) | (1 << PINC5); // включение подтягивающего резистора } void loop() { // Обработка нажатий на кнопки checkButton(0, 0x01, 0.0); checkButton(1, 0x02, 0.0); checkButton(2, 0x03, 1.25); checkButton(3, 0x04, 0.8); checkButton(4, 0x05, 1.1); checkButton(5, 0x06, 0.9); } void checkButton(uint8_t pin, uint16_t cmd, float value) { if (bit_is_clear(PINC, pin)) { sendCommand(cmd, value); if (cmd == 0x03) { frequency *= value; pwm_set_frequency(frequency); } else if (cmd == 0x04) { frequency *= value; pwm_set_frequency(frequency); } else if (cmd == 0x05) { dutyCycle *= value; pwm_set_duty_cycle(dutyCycle); } else if (cmd == 0x06) { dutyCycle *= value; pwm_set_duty_cycle(dutyCycle); } else if (cmd == 0x02) { pwm_disable(); // Выключение ШИМ } else if (cmd == 0x01) { pwm_enable(); // Включение ШИМ } command = cmd; _delay_ms(500); // Задержка для антидребезга } } void sendCommand(uint16_t cmd, float value) { uint16_t data = (uint16_t)(value * 16.0); data |= cmd << 4; uint8_t buffer[2]; buffer[0] = data >> 8; buffer[1] = data & 0xFF; i2c_write(PWM_SLAVE_ADDR, buffer, 2); Serial.print("Command: "); Serial.print(cmd); Serial.print(", Value: "); Serial.println(value, 4); }