8.Master_I2C_PWM/slave/slave.c
2023-06-26 20:22:20 +03:00

290 lines
11 KiB
C
Raw Permalink 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>
// #include <avr/interrupt.h>
// #define SLAVE_ADDRESS 9 // адрес устройства slave
// #define COMMAND_1 0x01 //команда включения шим
// #define COMMAND_2 0x02 //команда выключения шим
// #define COMMAND_3 0x03 //команда изменения частоты шим
// #define COMMAND_4 0x04 //команда изменения скважности шим
// #define COMMAND_5 0x05 //команда изменения скважности шим
// 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 &= ~((1 << COM1A1) | (1 << COM1A0));
// //Fast PWM (Быстрый ШИМ)
// TCCR1A |= (0 << WGM11) | (0 << WGM10);
// TCCR1B |= (0 << WGM13) | (0 << WGM12);
// TCCR1A |= (0 << COM1A1) | (0 << COM1A0) | (0 << COM1B1) | (0 << COM1B0); //шим отключен, нормальная работа порта
// TCCR1B = 0;
// // OCR1A = 0;
// // OCR1B = 0;
// }
// 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;
// for(int i = 0;i<100;i++){
// }
// if (buffer[0] == COMMAND_1) {
// Serial.print("cmd: 0x");
// Serial.println(buffer[0]);
// timer1_on(frequency, dutycycle);
// Serial.print(", data bytes: ");
// Serial.print(buffer[1], HEX);
// Serial.print(" ");
// Serial.println(buffer[2], HEX); // Включение ШИМ
// } else if (buffer[0] == COMMAND_2) {
// Serial.print("cmd: 0x");
// Serial.println(buffer[0]);
// timer1_off();
// Serial.print(", data bytes: ");
// Serial.print(buffer[1], HEX);
// Serial.print(" ");
// Serial.println(buffer[2], HEX); // Выключение ШИМ
// } else if (buffer[0] == COMMAND_3) {
// Serial.print("cmd: 0x");
// Serial.println(buffer[0]);
// frequency = (buffer[1] << 8) + buffer[2];
// Serial.print("frequency value: ");
// Serial.print(frequency);
// Serial.print(", data bytes: ");
// Serial.print(buffer[1], HEX);
// Serial.print(" ");
// Serial.println(buffer[2], HEX);
// } else if (buffer[0] == COMMAND_4) {
// Serial.print("cmd: 0x");
// Serial.println(buffer[0]);
// frequency = (buffer[1] << 8) + buffer[2];
// Serial.print("frequency value: ");
// Serial.print(frequency);
// Serial.print(", data bytes: ");
// Serial.print(buffer[1], HEX);
// Serial.print(" ");
// Serial.println(buffer[2], HEX);
// } else if (buffer[0] == COMMAND_5) {
// Serial.print("cmd: 0x");
// Serial.println(buffer[0]);
// dutycycle = buffer[1];
// Serial.print("dytycycle value: ");
// Serial.println(dutycycle);
// Serial.print(", data bytes: ");
// Serial.print(buffer[1], HEX);
// Serial.print(" ");
// Serial.println(buffer[2], HEX);
// } else if (buffer[0] == COMMAND_5) {
// Serial.print("cmd: 0x");
// Serial.println(buffer[0]);
// dutycycle = buffer[1];
// Serial.print("dytycycle value: ");
// Serial.println(dutycycle);
// Serial.print(", data bytes: ");
// Serial.print(buffer[1], HEX);
// Serial.print(" ");
// Serial.println(buffer[2], HEX);
// }
// cnt = 0;
// }
// }
#include <avr/io.h>
#include <avr/interrupt.h>
#define SLAVE_ADDRESS 9 // адрес устройства slave
#define COMMAND_1 0x01 //команда включения шим
#define COMMAND_2 0x02 //команда выключения шим
#define COMMAND_3 0x03 //команда изменения частоты шим
#define COMMAND_4 0x04 //команда изменения скважности шим
#define COMMAND_5 0x05 //команда изменения скважности шим
#define COMMAND_6 0x06 //команда изменения скважности шим
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 &= ~((1 << COM1A1) | (1 << COM1A0));
//Fast PWM (Быстрый ШИМ)
TCCR1A |= (0 << WGM11) | (0 << WGM10);
TCCR1B |= (0 << WGM13) | (0 << WGM12);
TCCR1A |= (0 << COM1A1) | (0 << COM1A0) | (0 << COM1B1) | (0 << COM1B0); //шим отключен, нормальная работа порта
TCCR1B = 0;
// OCR1A = 0;
// OCR1B = 0;
}
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;
Serial.println(" ");
for (int i = 0; i < cnt; i++) {
Serial.print(buffer[i], HEX); // вывод байтов в шестнадцатеричном формате
Serial.print(" ");
}
if (buffer[0] == COMMAND_1) {
timer1_on(frequency, dutycycle);
} else if (buffer[0] == COMMAND_2) {
timer1_off();
} else if (buffer[0] == COMMAND_3) {
frequency = (buffer[1] << 8) + buffer[2];
} else if (buffer[0] == COMMAND_4) {
frequency = (buffer[1] << 8) + buffer[2];
} else if (buffer[0] == COMMAND_5) {
dutycycle = buffer[1];
} else if (buffer[0] == COMMAND_6) {
dutycycle = buffer[1];
}
cnt = 0;
}
}