8.Master_I2C_PWM/main.c
zloihach 8930119b68 ref
2023-04-12 12:23:05 +03:00

90 lines
3.9 KiB
C

#include <avr/io.h>
#include <util/twi.h>
#include <avr/interrupt.h>
#define I2C_ADDRESS 0x20
#define BUTTON1_PIN 2
#define BUTTON2_PIN 3
#define BUTTON3_PIN 4
#define BUTTON4_PIN 5
#define BUTTON5_PIN 6
#define BUTTON6_PIN 7
int frequency = 1000; // Начальная частота ШИМ
int dutyCycle = 50; // Начальная скважность ШИМ
int pwmEnabled = 0; // ШИМ выключен по умолчанию
void i2cInit() {
TWSR = 0; // Установка предделителя TWPS в 0
TWBR = ((F_CPU / 100000UL) - 16) / 2; // Установка скорости передачи 100 кГц
TWCR = (1 << TWEN) | (1 << TWEA) | (1 << TWIE); // Включение TWI и прерываний
}
void i2cWaitForComplete() {
while (!(TWCR & (1 << TWINT))); // Ожидание завершения передачи данных
}
void i2cSendByte(uint8_t data) {
TWDR = data;
TWCR = (1 << TWINT) | (1 << TWEN);
}
void i2cSendData(uint8_t address, uint8_t* data, uint8_t length) {
TWCR = (1 << TWSTA) | (1 << TWEN) | (1 << TWINT); // Генерация START
i2cWaitForComplete();
i2cSendByte((address << 1) | TW_WRITE); // Отправка адреса устройства
i2cWaitForComplete();
for (uint8_t i = 0; i < length; i++) { // Отправка данных
i2cSendByte(data[i]);
i2cWaitForComplete();
}
TWCR = (1 << TWSTO) | (1 << TWINT) | (1 << TWEN); // Генерация STOP
}
void setPwmFrequency(int frequency) {
TCCR1A = (1 << COM1A1) | (1 << WGM11); // Включение режима Fast PWM и установка нормального режима работы на выводе OC1A
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); // Установка предделителя на 8, чтобы получить частоту
OCR1A = (F_CPU / (2 * 8 * frequency)) - 1; // Рассчет значения регистра OCR1A для заданной частоты
}
void setPwmDutyCycle(int dutyCycle) {
OCR1B = (dutyCycle * OCR1A) / 100; // Рассчет значения регистра OCR1B для заданной скважности
}
void enablePwm() {
pwmEnabled = 1;
TCCR1B |= (1 << CS10); // Включение таймера
}
void disablePwm() {
pwmEnabled = 0;
TCCR1B &= ~(1 << CS10); // Выключение таймера
}
void setup() {
i2cInit(); // Инициализация шины I2C
DDRB &= ~((1 << BUTTON1_PIN) | (1 << BUTTON2_PIN) | (1 << BUTTON3_PIN) | (1 << BUTTON4_PIN) | (1 << BUTTON5_PIN) | (1 << BUTTON6_PIN)); // Настройка пинов кнопок на вход
PORTB |= (1 << BUTTON1_PIN) | (1 << BUTTON2_PIN) | (1 << BUTTON3_PIN) | (1 << BUTTON4_PIN) | (1 << BUTTON5_PIN) | (1 << BUTTON6_PIN); // Включение внутренней подтяжки к питанию для пинов кнопок
DDRB |= (1 << PB1); // Настройка пина OC1A на выход
setPwmFrequency(frequency); // Установка начальной частоты ШИМ
setPwmDutyCycle(dutyCycle); // Установка начальной скважности ШИМ
enablePwm(); // Включение ШИМ
sei(); // Включение прерываний
}
void loop() {
// Чтение состояния кнопок и отправка данных на устройство по шине I2C
uint8_t buttonState = (PINB >> BUTTON1_PIN) & 0x3F; // Чтение состояния кнопок
uint8_t data[] = {buttonState}; // Формирование массива данных для отправки
i2cSendData(I2C_ADDRESS, data, sizeof(data)); // Отправка данных на устройство
_delay_ms(10); // Задержка для стабилизации состояния кнопок
}
int main() {
setup();
while (1) {
loop();
}
return 0;
}