8.Master_I2C_PWM/test.h
2023-06-21 03:02:25 +03:00

679 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// #include <avr/io.h>
// 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(uint8_t dutyCycle) {
// uint16_t value = ICR1 * dutyCycle / 100.0;
// OCR1A = value;
// }
// void pwm_init();
// void pwm_set_frequency(uint16_t frequency);
// void pwm_set_duty_cycle(uint8_t dutyCycle);
// #define F_CPU 16000000UL
// #define I2C_FREQ 100000UL
// #define I2C_PRESCALER 1
// #define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER)
// 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 data) {
// // загружаем данные в регистр TWDR
// TWDR = data;
// // отправляем данные
// TWCR = (1 << TWINT) | (1 << TWEN);
// // ожидаем пока данные будут успешно отправлены
// while (!(TWCR & (1 << TWINT)));
// }
// uint8_t i2c_read_ack() {
// // разрешаем отправку ACK после прочтения байта
// TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
// // ожидаем пока данные будут успешно прочитаны
// while (!(TWCR & (1 << TWINT)));
// // возвращаем прочитанный байт
// return TWDR;
// }
// uint8_t i2c_read_nack() {
// // запрещаем отправку ACK после прочтения байта
// TWCR = (1 << TWINT) | (1 << TWEN);
// // ожидаем пока данные будут успешно прочитаны
// while (!(TWCR & (1 << TWINT)));
// // возвращаем прочитанный байт
// return TWDR;
// }
// void i2c_init();
// void i2c_start();
// void i2c_stop();
// void i2c_write(uint8_t data);
// uint8_t i2c_read_ack();
// uint8_t i2c_read_nack();
// 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();
// // Инициализируем пины кнопок
// 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); // включение подтягивающего резистора
// Serial.begin(9600); // Инициализируем Serial монитор
// Serial.println("PWM Controller started!");
// sendCommand(0x01, 0.0); // Включить ШИМ при запуске
// }
// void loop() {
// // Обработка нажатий на кнопки
// checkButton(0, "Turn on PWM!", 0x01, 0.0);
// checkButton(1, "Turn off PWM!", 0x02, 0.0);
// checkButton(2, "Increase frequency!", 0x03, 1.25);
// checkButton(3, "Decrease frequency!", 0x04, 0.8);
// checkButton(4, "Increase duty cycle!", 0x05, 1.1);
// checkButton(5, "Decrease duty cycle!", 0x06, 0.9);
// }
// void checkButton(uint8_t pin, const char* message, uint16_t cmd, float value) {
// if (bit_is_clear(PINC, pin)) {
// Serial.println(message);
// delay(500);
// 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_set_duty_cycle(0);
// } else if (cmd == 0x01) {
// pwm_set_duty_cycle(dutyCycle);
// }
// command = cmd;
// }
// }
// void sendCommand(uint16_t cmd, float value) {
// if (cmd != 0x01 && cmd != 0x02) { // если команда изменения параметров
// switch (cmd) {
// case 0x03: // Увеличить частоту на 25% от текущего.
// value = frequency;
// value *= 0.25;
// break;
// case 0x04: // Уменьшить частоту на 20% от текущего.
// value = frequency;
// value *= 0.2;
// break;
// case 0x05: // Увеличить скважность на 10% от текущего.
// value = dutyCycle;
// value *= 0.1;
// break;
// case 0x06: // Уменьшить скважность на 10% от текущего.
// value = dutyCycle;
// value *= 0.1;
// break;
// }
// }
// uint16_t data = (uint16_t)(value * 16.0);
// data |= cmd << 4;
// i2c_start();
// i2c_write(PWM_SLAVE_ADDR << 1);
// i2c_write(data >> 8);
// i2c_write(data & 0xFF);
// i2c_stop();
// Serial.print("Sent command: ");
// Serial.print(cmd, HEX);
// Serial.print(", value: ");
// Serial.println(value);
// }
//VERSION #2
#include <avr/io.h>
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(uint8_t 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 pwm_init();
void pwm_set_frequency(uint16_t frequency);
void pwm_set_duty_cycle(uint8_t dutyCycle);
void pwm_enable();
void pwm_disable();
#define F_CPU 16000000UL
#define I2C_FREQ 100000UL
#define I2C_PRESCALER 1
#define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER)
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 data) {
// загружаем данные в регистр TWDR
TWDR = data;
// отправляем данные
TWCR = (1 << TWINT) | (1 << TWEN);
// ожидаем пока данные будут успешно отправлены
while (!(TWCR & (1 << TWINT)));
}
uint8_t i2c_read_ack() {
// разрешаем отправку ACK после прочтения байта
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
// ожидаем пока данные будут успешно прочитаны
while (!(TWCR & (1 << TWINT)));
// возвращаем прочитанный байт
return TWDR;
}
uint8_t i2c_read_nack() {
// запрещаем отправку ACK после прочтения байта
TWCR = (1 << TWINT) | (1 << TWEN);
// ожидаем пока данные будут успешно прочитаны
while (!(TWCR & (1 << TWINT)));
// возвращаем прочитанный байт
return TWDR;
}
void i2c_init();
void i2c_start();
void i2c_stop();
void i2c_write(uint8_t data);
uint8_t i2c_read_ack();
uint8_t i2c_read_nack();
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); // включение подтягивающего резистора
Serial.begin(9600); // Инициализируем Serial монитор
Serial.println("PWM Controller started!");
sendCommand(0x01, 0.0); // Включить ШИМ при запуске
}
void loop() {
// Обработка нажатий на кнопки
checkButton(0, "Turn on PWM!", 0x01, 0.0);
checkButton(1, "Turn off PWM!", 0x02, 0.0);
checkButton(2, "Increase frequency!", 0x03, 1.25);
checkButton(3, "Decrease frequency!", 0x04, 0.8);
checkButton(4, "Increase duty cycle!", 0x05, 1.1);
checkButton(5, "Decrease duty cycle!", 0x06, 0.9);
}
void checkButton(uint8_t pin, const char* message, uint16_t cmd, float value) {
if (bit_is_clear(PINC, pin)) {
Serial.println(message);
delay(500);
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;
}
}
void sendCommand(uint16_t cmd, float value) {
if (cmd != 0x01 && cmd != 0x02) { // если команда изменения параметров
switch (cmd) {
case 0x03: // Увеличить частоту на 25% от текущего.
value = frequency;
value *= 0.25;
break;
case 0x04: // Уменьшить частоту на 20% от текущего.
value = frequency;
value *= 0.2;
break;
case 0x05: // Увеличить скважность на 10% от текущего.
value = dutyCycle;
value *= 0.1;
break;
case 0x06: // Уменьшить скважность на 10% от текущего.
value = dutyCycle;
value *= 0.1;
break;
}
}
uint16_t data = (uint16_t)(value * 16.0);
data |= cmd << 4;
i2c_start();
i2c_write(PWM_SLAVE_ADDR << 1);
i2c_write(data >> 8);
i2c_write(data & 0xFF);
i2c_stop();
Serial.print("Sent command: ");
Serial.print(cmd, HEX);
Serial.print(", value: ");
Serial.println(value);
// uint16_t data = (uint16_t)(value * 16.0);
// data |= cmd << 4;
// i2c_start();
// i2c_write(PWM_SLAVE_ADDR << 1);
// i2c_write(data >> 8);
// Serial.print("Sent byte 1: ");
// Serial.println(data >> 8, HEX);
// i2c_write(data & 0xFF);
// Serial.print("Sent byte 2: ");
// Serial.println(data & 0xFF, HEX);
// i2c_stop();
// Serial.print("Sent command: ");
// Serial.print(cmd, HEX);
// Serial.print(", value: ");
// Serial.println(value);
}
//VERSION 3.x
// #include <avr/io.h>
// #include <util/delay.h>
// #include <stdbool.h>
// void i2c_init();
// void i2c_start();
// void i2c_stop();
// void i2c_write(uint8_t data);
// uint8_t i2c_read_ack();
// uint8_t i2c_read_nack();
// #define F_CPU 16000000UL
// #define I2C_FREQ 100000UL
// #define I2C_PRESCALER 1
// #define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER)
// 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 data) {
// // загружаем данные в регистр TWDR
// TWDR = data;
// // отправляем данные
// TWCR = (1 << TWINT) | (1 << TWEN);
// // ожидаем пока данные будут успешно отправлены
// while (!(TWCR & (1 << TWINT)));
// }
// uint8_t i2c_read_ack() {
// // разрешаем отправку ACK после прочтения байта
// TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
// // ожидаем пока данные будут успешно прочитаны
// while (!(TWCR & (1 << TWINT)));
// // возвращаем прочитанный байт
// return TWDR;
// }
// uint8_t i2c_read_nack() {
// // запрещаем отправку ACK после прочтения байта
// TWCR = (1 << TWINT) | (1 << TWEN);
// // ожидаем пока данные будут успешно прочитаны
// while (!(TWCR & (1 << TWINT)));
// // возвращаем прочитанный байт
// return TWDR;
// }
// #ifndef PWM_H
// #define PWM_H
// void pwm_init();
// void pwm_set_frequency(uint16_t frequency);
// void pwm_set_duty_cycle(uint8_t dutyCycle);
// void pwm_enable();
// void pwm_disable();
// #endif
// 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(uint8_t 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); // Выключение ШИМ
// }
// #define F_CPU 16000000UL
// #define I2C_FREQ 100000UL
// #define I2C_PRESCALER 1
// #define I2C_BITRATE ((F_CPU / I2C_FREQ) - 16) / (2 * I2C_PRESCALER)
// #define BUTTON_PIN_CNT 6
// 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;
// bool is_button_pressed(uint8_t pin);
// void process_button_press(uint8_t pin);
// void send_command(uint16_t cmd, float value);
// int main(void) {
// i2c_init();
// pwm_init();
// pwm_enable(); // Включение ШИМ
// for (uint8_t i = 0; i < BUTTON_PIN_CNT; i++) {
// DDRC &= ~(1 << BUTTON_PIN[i]);
// PORTC |= (1 << BUTTON_PIN[i]);
// }
// Serial.begin(9600); // Инициализируем Serial монитор
// Serial.println("PWM Controller started!");
// send_command(0x01, 0.0); // Включить ШИМ при запуске
// while (true) {
// for (uint8_t i = 0; i < BUTTON_PIN_CNT; i++) {
// if (is_button_pressed(BUTTON_PIN[i])) {
// process_button_press(BUTTON_PIN[i]);
// _delay_ms(500);
// }
// }
// }
// }
// bool is_button_pressed(uint8_t pin) {
// return bit_is_clear(PINC, pin);
// }
// void process_button_press(uint8_t pin) {
// switch (pin) {
// case 0:
// send_command(0x01, 0.0);
// Serial.println("Turn on PWM!");
// break;
// case 1:
// send_command(0x02, 0.0);
// Serial.println("Turn off PWM!");
// break;
// case 2:
// if (frequency * 1.25 < 10000) {
// frequency *= 1.25;
// pwm_set_frequency(frequency);
// send_command(0x03, 1.25);
// Serial.println("Increased frequency!");
// } else {
// Serial.println("Maximum frequency reached!");
// }
// break;
// case 3:
// if (frequency * 0.8 > 1) {
// frequency *= 0.8;
// pwm_set_frequency(frequency);
// send_command(0x04, 0.8);
// Serial.println("Decreased frequency!");
// } else {
// Serial.println("Minimum frequency reached!");
// }
// break;
// case 4:
// if (dutyCycle * 1.1 <= 100) {
// dutyCycle *= 1.1;
// pwm_set_duty_cycle(dutyCycle);
// send_command(0x05, 1.1);
// Serial.println("Increased duty cycle!");
// } else {
// Serial.println("Maximum duty cycle reached!");
// }
// break;
// case 5:
// if (dutyCycle * 0.9 >= 0) {
// dutyCycle *= 0.9;
// pwm_set_duty_cycle(dutyCycle);
// send_command(0x06, 0.9);
// Serial.println("Decreased duty cycle!");
// } else {
// Serial.println("Minimum duty cycle reached!");
// }
// break;
// default:
// break;
// }
// }
// void send_command(uint16_t cmd, float value) {
// if (cmd != 0x01 && cmd != 0x02) { // если команда изменения параметров
// switch (cmd) {
// case 0x03: // Увеличить частоту на 25% от текущего.
// value = frequency;
// value *= 0.25;
// break;
// case 0x04: // Уменьшить частоту на 20% от текущего.
// value = frequency;
// value *= 0.2;
// break;
// case 0x05: // Увеличить скважность на 10% от текущего.
// value = dutyCycle;
// value *= 0.1;
// break;
// case 0x06: // Уменьшить скважность на 10% от текущего.
// value = dutyCycle;
// value *= 0.1;
// break;
// }
// }
// uint16_t data = (uint16_t)(value * 16.0);
// data |= cmd << 4;
// i2c_start();
// i2c_write(PWM_SLAVE_ADDR << 1);
// i2c_write(data >> 8);
// i2c_write(data & 0xFF);
// i2c_stop();
// Serial.print("Sent command: ");
// Serial.print(cmd, HEX);
// Serial.print(", value: ");
// Serial.println(value);
// }
///test
// #include <Wire.h>
// #define PWM_ADDR 9 // Адрес устройства на шине I2C
// void setup() {
// Wire.begin();
// Serial.begin(9600);
// Serial.println("PWM Master device started!");
// Serial.println("I2C connection established");
// }
// void loop() {
// // Генерация случайного значения ШИМ-сигнала
// int pwmValue = random(256);
// // Отправка значения по шине I2C на адрес устройства PWM_ADDR
// Wire.beginTransmission(PWM_ADDR);
// Wire.write(pwmValue);
// Wire.endTransmission();
// Serial.print("Sent PWM value: ");
// Serial.println(pwmValue);
// delay(1000); // Пауза между отправкой нового значения
// }