diff --git a/main.c b/main.c index 909a9f1..1b53008 100644 --- a/main.c +++ b/main.c @@ -1,232 +1,256 @@ -#define F_CPU 16000000UL -#define I2C_FREQ 100000UL -#define I2C_PRESCALER 1 -#define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER) - -#include -#include -#include - -float pwm_frequency = 1.0; -float pwm_duty_cycle = 0.5; - -volatile uint8_t pwm_enabled = 0; -volatile uint8_t pwm_changed = 0; - -void i2c_init() { - TWBR = I2C_BITRATE; -} - -void i2c_start() { - TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); - while (!(TWCR & (1 << TWINT))) - ; -} - -void i2c_stop() { - TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); - while (TWCR & (1 << TWSTO)) - ; -} - -void i2c_write(uint8_t data) { - TWDR = data; - TWCR = (1 << TWINT) | (1 << TWEN); - while (!(TWCR & (1 << TWINT))) - ; -} - -uint8_t i2c_read_ack() { - TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); - while (!(TWCR & (1 << TWINT))) - ; - return TWDR; -} - -uint8_t i2c_read_nack() { - TWCR = (1 << TWINT) | (1 << TWEN); - while (!(TWCR & (1 << TWINT))) - ; - return TWDR; -} - -const uint8_t PWM_SLAVE_ADDR = 9; - -void pwm_enable() { - pwm_enabled = 1; - pwm_changed = 1; -} - -void pwm_disable() { - pwm_enabled = 0; - pwm_changed = 1; -} - -void setPWMFrequency(float frequency) { - if (frequency < 1.0 || frequency > 50000.0) { - return; // Недопустимая частота - } - pwm_frequency = frequency; - pwm_changed = 1; -} - -void setPWMDutyCycle(float duty_cycle) { - if (duty_cycle < 0.0 || duty_cycle > 1.0) { - return; // Недопустимый коэффициент заполнения - } - pwm_duty_cycle = duty_cycle; - pwm_changed = 1; -} - -void pwm_check_state() { - if (pwm_enabled) { - // Включаем пин ШИМ - реализация зависит от аппаратной платформы - Serial.print("PWM enabled. Frequency: "); - Serial.print(pwm_frequency); - Serial.print(" Hz, duty cycle: "); - Serial.println(pwm_duty_cycle); - } else { - // Выключаем пин ШИМ - реализация зависит от аппаратной платформы - Serial.println("PWM disabled"); - } -} - -void pwm_set_frequency(float frequency) { - // Устанавливаем частоту ШИМ - реализация зависит от аппаратной платформы - Serial.print("Setting PWM frequency to: "); - Serial.println(frequency); -} - -void pwm_set_duty_cycle(float duty_cycle) { - // Устанавливаем коэффициент заполнения ШИМ - реализация зависит от аппаратной платформы - Serial.print("Setting PWM duty cycle to: "); - Serial.println(duty_cycle); -} - -void enablePWM() { - pwm_enable(); - // Включаем ШИМ - sendCommand(0x01, 0.0); -} - -void disablePWM() { - // Выключаем ШИМ - sendCommand(0x02, 0.0); - pwm_disable(); -} - -void increaseFrequency() { - setPWMFrequency(pwm_frequency * 1.25); - // Выключаем ШИМ, отправляем команду и включаем обратно - disablePWM(); - sendCommand(0x03, pwm_frequency); - enablePWM(); -} - -void decreaseFrequency() { - setPWMFrequency(pwm_frequency * 0.8); - // Выключаем ШИМ, отправляем команду и включаем обратно - disablePWM(); - sendCommand(0x04, pwm_frequency); - enablePWM(); -} - -void increaseDutyCycle() { - if (pwm_duty_cycle < 0.9) { - setPWMDutyCycle(pwm_duty_cycle * 1.1); - // Выключаем ШИМ, отправляем команду и включаем обратно - disablePWM(); - sendCommand(0x05, pwm_duty_cycle); - enablePWM(); - } else { - Serial.println("Maximum duty cycle reached!"); - } -} - -void decreaseDutyCycle() { - if (pwm_duty_cycle > 0.1) { - setPWMDutyCycle(pwm_duty_cycle*0.9); - // Выключаем ШИМ, отправляем команду и включаем обратно - disablePWM(); - sendCommand(0x06, pwm_duty_cycle); - enablePWM(); - } else { - Serial.println("Minimum duty cycle reached!"); - } -} - -void checkButton(uint8_t pin, const char* message, void (*command)()) { - if (bit_is_clear(PINC, pin)) { - Serial.println(message); - delay(1000); - command(); - } -} - -void setup() { - i2c_init(); - DDRC &= ~(1 << PINC0) & ~(1 << PINC1) & ~(1 << PINC2) & ~(1 << PINC3) & ~(1 << PINC4) & ~(1 << PINC5); - PORTC |= (1 << PINC0) | (1 << PINC1) | (1 << PINC2) | (1 << PINC3) | (1 << PINC4) | (1 << PINC5); - Serial.begin(9600); - Serial.println("PWM Controller started!"); - sendCommand(0x01, 0.0); -} - -void loop() { - checkButton(0, "Turn on PWM!", enablePWM); - checkButton(1, "Turn off PWM!", disablePWM); - checkButton(2, "Increase frequency by 25%!", increaseFrequency); - checkButton(3, "Decrease frequency by 20%!", decreaseFrequency); - checkButton(4, "Increase duty cycle by 10%!", increaseDutyCycle); - checkButton(5, "Decrease duty cycle by 10%!", decreaseDutyCycle); - - // Обновляем состояние ШИМ, если что-то изменилось - if (pwm_changed) { - pwm_changed = 0; - pwm_check_state(); - if (pwm_enabled) { - pwm_set_frequency(pwm_frequency); - pwm_set_duty_cycle(pwm_duty_cycle); - } - } -} - - -void sendCommand(uint8_t cmd, float value) { - // Приводим значение к 12 битам для целой части и 4 битам для дробной части - uint16_t integer_part = (uint16_t)value; - uint8_t fractional_part = (uint8_t)((value - integer_part) * 16); - - // Проверяем, чтобы значение не превышало допустимых границ - if (integer_part > 0xFFF) { - integer_part = 0xFFF; - } - if (fractional_part > 0xF) { - fractional_part = 0xF; - } - - // Формируем 4 байта данных для отправки - uint8_t upper_byte = (integer_part >> 4) & 0xFF; - uint8_t lower_byte = ((integer_part & 0xF) << 4) | (fractional_part & 0xF); - - i2c_start(); - i2c_write(PWM_SLAVE_ADDR << 1); - i2c_write(cmd); - i2c_write(upper_byte); - i2c_write(lower_byte); - i2c_stop(); - - Serial.print("Sent command: 0x"); - Serial.print(cmd, HEX); - Serial.print(", value: "); - Serial.print(value); - Serial.print(", cmd value: "); - Serial.print((integer_part << 4) | fractional_part); - Serial.print(", data bytes: 0x"); - Serial.print(upper_byte, HEX); - Serial.print(" "); - Serial.println(lower_byte, HEX); -} - - - +//#define F_CPU 16000000UL +//#define I2C_FREQ 100000UL +//#define I2C_PRESCALER 1 +//#define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER) +// +//#include +//#include +//#include +// +//float pwm_frequency = 1.0; +//float pwm_duty_cycle = 0.5; +// +//volatile uint8_t pwm_enabled = 0; +//volatile uint8_t pwm_changed = 0; +// +//void i2c_init() { +// TWBR = I2C_BITRATE; +//} +// +//void i2c_start() { +// TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); +// while (!(TWCR & (1 << TWINT))) +// ; +//} +// +//void i2c_stop() { +// TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); +// while (TWCR & (1 << TWSTO)) +// ; +//} +// +//void i2c_write(uint8_t data) { +// TWDR = data; +// TWCR = (1 << TWINT) | (1 << TWEN); +// while (!(TWCR & (1 << TWINT))) +// ; +//} +// +//uint8_t i2c_read_ack() { +// TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); +// while (!(TWCR & (1 << TWINT))) +// ; +// return TWDR; +//} +// +//uint8_t i2c_read_nack() { +// TWCR = (1 << TWINT) | (1 << TWEN); +// while (!(TWCR & (1 << TWINT))) +// ; +// return TWDR; +//} +// +//const uint8_t PWM_SLAVE_ADDR = 9; +// +//void pwm_enable() { +// pwm_enabled = 1; +// pwm_changed = 1; +//} +// +//void pwm_disable() { +// pwm_enabled = 0; +// pwm_changed = 1; +//} +// +//void setPWMFrequency(float frequency) { +// if (frequency < 1.0 || frequency > 50000.0) { +// return; // Недопустимая частота +// } +// pwm_frequency = frequency; +// pwm_changed = 1; +//} +// +//void setPWMDutyCycle(float duty_cycle) { +// if (duty_cycle < 0.0 || duty_cycle > 1.0) { +// return; // Недопустимый коэффициент заполнения +// } +// pwm_duty_cycle = duty_cycle; +// pwm_changed = 1; +//} +// +//void pwm_check_state() { +// if (pwm_enabled) { +// // Включаем пин ШИМ - реализация зависит от аппаратной платформы +// Serial.print("PWM enabled. Frequency: "); +// Serial.print(pwm_frequency); +// Serial.print(" Hz, duty cycle: "); +// Serial.println(pwm_duty_cycle); +// } else { +// // Выключаем пин ШИМ - реализация зависит от аппаратной платформы +// Serial.println("PWM disabled"); +// } +//} +// +//void pwm_set_frequency(float frequency) { +// // Устанавливаем частоту ШИМ - реализация зависит от аппаратной платформы +// Serial.print("Setting PWM frequency to: "); +// Serial.println(frequency); +//} +// +//void pwm_set_duty_cycle(float duty_cycle) { +// // Устанавливаем коэффициент заполнения ШИМ - реализация зависит от аппаратной платформы +// Serial.print("Setting PWM duty cycle to: "); +// Serial.println(duty_cycle); +//} +// +//void enablePWM() { +// pwm_enable(); +// // Включаем ШИМ +// sendCommand(0x01, 0.0); +//} +// +//void disablePWM() { +// // Выключаем ШИМ +// sendCommand(0x02, 0.0); +// pwm_disable(); +//} +// +//void increaseFrequency() { +// setPWMFrequency(pwm_frequency * 1.25); +// // Выключаем ШИМ, отправляем команду и включаем обратно +// disablePWM(); +// sendCommand(0x03, pwm_frequency); +// enablePWM(); +//} +// +//void decreaseFrequency() { +// setPWMFrequency(pwm_frequency * 0.8); +// // Выключаем ШИМ, отправляем команду и включаем обратно +// disablePWM(); +// sendCommand(0x04, pwm_frequency); +// enablePWM(); +//} +// +//void increaseDutyCycle() { +// if (pwm_duty_cycle < 0.9) { +// setPWMDutyCycle(pwm_duty_cycle * 1.1); +// // Выключаем ШИМ, отправляем команду и включаем обратно +// disablePWM(); +// sendCommand(0x05, pwm_duty_cycle); +// enablePWM(); +// } else { +// Serial.println("Maximum duty cycle reached!"); +// } +//} +// +//void decreaseDutyCycle() { +// if (pwm_duty_cycle > 0.1) { +// setPWMDutyCycle(pwm_duty_cycle*0.9); +// // Выключаем ШИМ, отправляем команду и включаем обратно +// disablePWM(); +// sendCommand(0x06, pwm_duty_cycle); +// enablePWM(); +// } else { +// Serial.println("Minimum duty cycle reached!"); +// } +//} +// +//void checkButton(uint8_t pin, const char* message, void (*command)()) { +// if (bit_is_clear(PINC, pin)) { +// Serial.println(message); +// delay(200); +// command(); +// } +//} +// +//void setup() { +// i2c_init(); +// DDRC &= ~(1 << PINC0) & ~(1 << PINC1) & ~(1 << PINC2) & ~(1 << PINC3) & ~(1 << PINC4) & ~(1 << PINC5); +// PORTC |= (1 << PINC0) | (1 << PINC1) | (1 << PINC2) | (1 << PINC3) | (1 << PINC4) | (1 << PINC5); +// Serial.begin(9600); +// Serial.println("PWM Controller started!"); +// sendCommand(0x01, 0.0); +//} +// +//void loop() { +// checkButton(0, "Turn on PWM!", enablePWM); +// checkButton(1, "Turn off PWM!", disablePWM); +// checkButton(2, "Increase frequency by 25%!", increaseFrequency); +// checkButton(3, "Decrease frequency by 20%!", decreaseFrequency); +// checkButton(4, "Increase duty cycle by 10%!", increaseDutyCycle); +// checkButton(5, "Decrease duty cycle by 10%!", decreaseDutyCycle); +// +// // Обновляем состояние ШИМ, если что-то изменилось +// if (pwm_changed) { +// pwm_changed = 0; +// pwm_check_state(); +// if (pwm_enabled) { +// pwm_set_frequency(pwm_frequency); +// pwm_set_duty_cycle(pwm_duty_cycle); +// } +// } +//} +// +// +//void sendCommand(uint8_t cmd, float value) { +// // Приводим значение к 12 битам для целой части и 4 битам для дробной части +// uint16_t integer_part = (uint16_t)value; +// uint8_t fractional_part = (uint8_t)((value - integer_part) * 16); +// +// // Проверяем, чтобы значение не превышало допустимых границ +// if (integer_part > 0xFFF) { +// integer_part = 0xFFF; +// } +// if (fractional_part > 0xF) { +// fractional_part = 0xF; +// } +// +// // Формируем 4 байта данных для отправки +// uint8_t upper_byte = (integer_part >> 4) & 0xFF; +// uint8_t lower_byte = ((integer_part & 0xF) << 4) | (fractional_part & 0xF); +// +// i2c_start(); +// i2c_write(PWM_SLAVE_ADDR << 1); +// i2c_write(cmd); +// i2c_write(upper_byte); +// i2c_write(lower_byte); +// i2c_stop(); +// +// Serial.print("Sent command: 0x"); +// Serial.print(cmd, HEX); +// Serial.print(", value: "); +// Serial.print(value); +// Serial.print(", cmd value: "); +// Serial.print((integer_part << 4) | fractional_part); +// Serial.print(", data bytes: 0x"); +// Serial.print(upper_byte, HEX); +// Serial.print(" "); +// Serial.println(lower_byte, HEX); +//} +// +// +// +// +//// void sendCommand(uint8_t cmd, float value) { +//// uint16_t cmd_value = ((uint16_t)cmd << 8) | (uint16_t)(value * 16); +//// uint8_t upper_byte = cmd_value >> 8; +//// uint8_t lower_byte = cmd_value & 0xFF; +// +//// i2c_start(); +//// i2c_write(PWM_SLAVE_ADDR << 1); +//// i2c_write(cmd); +//// i2c_write(upper_byte); +//// i2c_write(lower_byte); +//// i2c_stop(); +// +//// Serial.print("Sent command: 0x"); +//// Serial.print(cmd, HEX); +//// Serial.print(", value: "); +//// Serial.print(cmd_value / 16); +//// Serial.print(", cmd value: "); +//// Serial.print(cmd_value); +//// Serial.print(", data bytes: 0x"); +//// Serial.print(upper_byte, HEX); +//// Serial.print(" "); +//// Serial.println(lower_byte, HEX); +//// } \ No newline at end of file