#define F_CPU 8000000UL
#include <avr/io.h>
#define _data 3 // устанавливаем пин вывода данных в сдвиговые регистры
#define _clock 4 // устанавливаем пин clock
#define _latch 5 // устанавливаем пин защёлки
#define SIZE_SCREEN 4
unsigned char buffer [SIZE_SCREEN]; //создаем буфер буфер экрана (выяснить какой тип данных применить)
int record (); //прототип функции для записи в сдвиговые регистры
int main (void)
{
DDRC = 0b00111000;
PORTC |= (1<<_clock); // устанавливаем clock в 1 для предотвращения ложного срабатывания
PORTC |= (1<<_latch); // поднимаем защелку
PORTC |= (1<<_data); // устанавливаем на выходе дата 1
}
int record ()
{
PORTC &= ~(1<<_latch); // опускаем защелку
for (int x = 0; x<SIZE_SCREEN; x++) //цикл для переборки байтов в массиве (уточнить как храниться число)
{
for (int y = 0; y<8; y++) // цикл для перебора битов в байте и подачи их на выход
{
if ((buffer[x] & (1<<y)) == 0) // накладываем побитовую маску для считывания нужного бита
{
PORTC &= ~(1<<_data); // если ответ 0, выставляем на входе регистра 0
}
else
{
PORTC |= (1<<_data); //иначе, выставляем на входе регистра 1
}
PORTC &= ~(1<<_clock); // устанавливаем clock в 0, переводим регистр в режим ожидания данных
PORTC |= (1<<_clock); // устанавливаем clock в 1, записываем данные в регистр
}
}
PORTC |= (1<<_latch); // поднимаем защелку включаем светодиоды
}
Цитата: Shaman#define _data 3 // устанавливаем пинНаверное, не устанавливаем пин, а назначаем разряд порта.
Цитата: ShamanPORTC |= (1<<_clock)Честно говоря, мне совсем не нравятся эти записи "1<<Clock". Считаю, что в этом месте надо чётко писать "Clock" без всяких 1<<
#define _data 8 // назначаем разряд 3 порта как сигнал Data
Это потому что на порт посмотреть как на биты, слева старший, справа младший, то он выглядит как бинарное число '00001000', т.е. '8' в нашем обиходе.#define _data 1<<3 // назначаем разряд 3 порта как сигнал Data
Здесь записано, что 1 сдвинута логически влево три раза, т.е. на три разряда. Бинарно это выглядит так#define _clock 1<<4 // назначаем разряд порта для сигнала clock
Если сделать так, то процедура изменения значения порта станет выглядеть такPORTC |= _clock; // устанавливаем clock в "1"
PORTC &= ~_clock; // устанавливаем clock в "0"
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#define _data_1 PORTC |= (1<<3) // Выбираем пин для вывода данных в сдвиговые регистры и устанавливаем на нём 1 путём установки порта и назначения разряда соответствующего пину
#define _data_0 PORTC &= ~(1<<3) // -.- устанавливаем на нём 0 -.-
#define _clock_high PORTC |= (1<<4) // Выбираем пин clock и устанавливаем на нём высокий уровень
#define _clock_low PORTC &= ~(1<<4) // Выбираем пин clock и устанавливаем на нём низкий уровень
#define _latch_up PORTC |= (1<<5) // Выбираем пин защёлки и поднимаем её
#define _latch_down PORTC &= ~(1<<5) // Выбираем пин защёлки и опускаем её
#define SIZE_SCREEN 4 //размер буфера экрана
unsigned char buffer [SIZE_SCREEN]; //создаем буфер буфер экрана
int record (); //прототип функции для записи в сдвиговые регистры
int main (void)
{
DDRC = 0b00111000; //устанавливаем необходимые пины на вывод
_clock_high; // для предотвращения ложного срабатывания
_latch_up; // поднимаем защелку
while (1)
{
buffer[0] = 0b01010101;
buffer[1] = 0b01010101;
buffer[2] = 0b01010101;
buffer[3] = 0b01010101;
record ();
_delay_ms(50);
buffer[0] = 0b10101010;
buffer[1] = 0b10101010;
buffer[2] = 0b10101010;
buffer[3] = 0b10101010;
record ();
_delay_ms(50);
}
}
int record ()
{
_latch_down; // опускаем защелку
for (int x = 0; x<SIZE_SCREEN; x++) //цикл для переборки байтов в массиве (уточнить как храниться число)
{
for (int y = 7; y>=0; y--) // цикл для перебора битов в байте и подачи их на выход
{
_clock_low; // переводим регистры в режим ожидания данных
if ((buffer[x] & (1<<y)) == 0) // накладываем побитовую маску для считывания нужного бита
{
_data_0; // если ответ 0, выставляем на входе регистра 0
}
else
{
_data_1; //иначе, выставляем на входе регистра 1
}
_clock_high; // записываем данные в регистр
}
}
_latch_up; // поднимаем защелку, включаем светодиоды
}
#define _data 8 // назначаем разряд 3 порта как сигнал Data
#define _data 1<<3 // назначаем разряд 3 порта как сигнал Data
#define _clock 1<<4 // назначаем разряд порта для сигнала clock
PORTC |= _clock; // устанавливаем clock в "1"
PORTC &= ~_clock; // устанавливаем clock в "0"
[/quote]#define _data_1 PORTC |= (1<<3) // Выбираем пин для вывода данных в сдвиговые регистры и устанавливаем на нём 1 путём установки порта и назначения разряда соответствующего пину
#define _data_0 PORTC &= ~(1<<3) // -.- устанавливаем на нём 0 -.-
#define _clock_high PORTC |= (1<<4) // Выбираем пин clock и устанавливаем на нём высокий уровень
#define _clock_low PORTC &= ~(1<<4) // Выбираем пин clock и устанавливаем на нём низкий уровень
#define _latch_up PORTC |= (1<<5) // Выбираем пин защёлки и поднимаем её
#define _latch_down PORTC &= ~(1<<5) // Выбираем пин защёлки и опускаем её
это уже использование конкретного бита на конкретном порту и буде возникнет необходимость поменять порт и бит нужно всего лишь исправить несколько строчек кода, а не шарахаться по всему листингу.int left_stop ()
{
_scvagnost;
_pwm_on
_pwm_open_BrRl;
_Null;
_Green = ABC[4];
_Blue_right_Red_left = ABC[4];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(100);
_Null;
_Green = ABC[5];
_Blue_right_Red_left = ABC[5];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(100);
_Null;
_Green = ABC[6];
_Blue_right_Red_left = ABC[6];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(100);
_Null;
_Green = ABC[7];
_Blue_right_Red_left = ABC[7];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(100);
_Null;
_Green = ABC[7] | ABC [4];
_Blue_right_Red_left = ABC[7] | ABC [4];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(100);
_Null;
_Green = ABC[7] | ABC [5];
_Blue_right_Red_left = ABC[7] | ABC [5];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(100);
_Null;
_Green = ABC[7] | ABC [6];
_Blue_right_Red_left = ABC[7] | ABC [6];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(100);
_Null;
_Green = ABC[7] | ABC [6] | ABC [4];
_Blue_right_Red_left = ABC[7] | ABC [6] | ABC [4];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(100);
_Null;
_Green = ABC[7] | ABC [6] | ABC [5];
_Blue_right_Red_left = ABC[7] | ABC [6] | ABC [5];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(50);
_Null;
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(50);
_Null;
_Green = ABC[7] | ABC [6] | ABC [5];
_Blue_right_Red_left = ABC[7] | ABC [6] | ABC [5];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(50);
_Null;
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(50);
_Null;
_Green = ABC[7] | ABC [6] | ABC [5];
_Blue_right_Red_left = ABC[7] | ABC [6] | ABC [5];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(50);
_Null;
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(50);
_Null;
_Green = ABC[7] | ABC [6] | ABC [5];
_Blue_right_Red_left = ABC[7] | ABC [6] | ABC [5];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(50);
_Null;
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(50);
_Null;
_Green = ABC[7] | ABC [6] | ABC [5];
_Blue_right_Red_left = ABC[7] | ABC [6] | ABC [5];
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_delay_ms(50);
_Null;
_Red_right_Blue_left = ABC[3] | ABC[2] | ABC[1] | ABC[0];
_RGB = ABC[0];
record ();
_pwm_close_BrRl;
_pwm_off;
}
TCCR1B &= ~(1<<CS10); //выключаем шим
_delay_ms(500);
TCNT1 = 300;
_delay_ms(500);
TCNT1 = 100;
_delay_ms(500);
TCNT1 = 300;
_delay_ms(500);
TCNT1 = 100;
_delay_ms(500);
TCNT1 = 300;
_delay_ms(500);
TCNT1 = 100;
_delay_ms(500);
TCNT1 = 300;
_delay_ms(500);
TCNT1 = 100;
_delay_ms(500);
TCNT1 = 300;
_delay_ms(500);
TCNT1 = 100;
_delay_ms(500);
TCNT1 = 300;
_delay_ms(500);
TCNT1 = 100;
_delay_ms(500);
TCNT1 = 300;
_delay_ms(500);
TCNT1 = 100;
_delay_ms(500);
TCNT1 = 300;
_delay_ms(500);
_TCCR1B &= ~(1<<CS10); //выключаем шим
TCNT1H = 0b00000000;
TCNT1L = 0b00000011;
_delay_ms(500);
TCNT1H = 0b00000111;
TCNT1L = 0b00000000;
_delay_ms(500);
TCNT1H = 0b00000000;
TCNT1L = 0b00000011;
_delay_ms(500);
TCNT1H = 0b00000111;
TCNT1L = 0b00000000;
_delay_ms(500);
TCNT1H = 0b00000000;
TCNT1L = 0b00000011;
_delay_ms(500);
TCNT1H = 0b00000111;
TCNT1L = 0b00000000;
_delay_ms(500);
TCNT1H = 0b00000000;
TCNT1L = 0b00000011;
_delay_ms(500);
TCNT1H = 0b00000111;
TCNT1L = 0b00000000;
_delay_ms(500);
TCNT1H = 0b00000000;
TCNT1L = 0b00000011;
_delay_ms(500);
TCNT1H = 0b00000111;
TCNT1L = 0b00000000;
_delay_ms(500);
TCNT1H = 0b00000000;
TCNT1L = 0b00000011;
_delay_ms(500);
TCNT1H = 0b00000111;
TCNT1L = 0b00000000;
_delay_ms(500);
#define F_CPU 1000000UL //Скорость контроллера
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
#include <avr/interrupt.h>
// настраиваем скорость прердачи UART
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD-1
//
#define _data_1 PORTC |= (1<<3) // Выбираем пин для вывода данных в сдвиговые регистры и устанавливаем на нём 1 путём установки порта и назначения разряда соответствующего пину
#define _data_0 PORTC &= ~(1<<3) // -.- устанавливаем на нём 0 -.-
#define _clock_high PORTC |= (1<<4) // Выбираем пин clock и устанавливаем на нём высокий уровень
#define _clock_low PORTC &= ~(1<<4) // Выбираем пин clock и устанавливаем на нём низкий уровень
#define _latch_up PORTC |= (1<<5) // Выбираем пин защёлки и поднимаем её
#define _latch_down PORTC &= ~(1<<5) // Выбираем пин защёлки и опускаем её
//Выбор портов для управления морганием и управлением PWM
#define _flash_G_hight PORTD |= (1<<2) //Выбираем пин out enable для Green и устанавливаем на нём высокий уровень
#define _flash_G_low PORTD &= ~(1<<2) //Выбираем пин out enable для Green и устанавливаем на нём низкий уровень
#define _flash_RGB_hight PORTD |= (1<<3) //Выбираем пин out enable для _RGB и устанавливаем на нём высокий уровень
#define _flash_RGB_low PORTD &= ~(1<<3) //Выбираем пин out enable для _RGB и устанавливаем на нём низкий уровень
#define _pwm_close_RrBl PORTC |= (1<<1) //устанавливаем на пине 1 порта C 1
#define _pwm_open_RrBl PORTC &= ~(1<<1) //устанавливаем на пине 1 порта C 0 тем самым пропуская PWM на выход
#define _pwm_close_BrRl PORTC |= (1<<2) //устанавливаем на пине 2 порта C 1
#define _pwm_open_BrRl PORTC &= ~(1<<2) //устанавливаем на пине 2 порта C 0 тем самым пропуская PWM на выход
#define _pwm_pass PORTC &= ~(1<<0) //пропускаем PWM на вход элемента 2ИЛИ-НЕ Б
#define _pwm_drop PORTC |= (1<<0) //не пропускаем PWM на вход элемента 2ИЛИ-НЕ Б
#define _pwm_on TCCR1B |= (1<<CS10) //включаем шим
#define _pwm_off TCCR1B &= ~(1<<CS10) //выключаем шим
//Блок регулировки задержек
#define _turn_signal_spd _delay_ms(100) //скорость бегущей строки поворотника
#define _turn_signal_fsdp _delay_ms(200) //скорость моргания поворотника
#define _blink_spd _delay_ms(200) //скорость моргания моргалки ))
#define _scvagnost OCR1A = 700 //устанавливаем регистр сравнения рагулируя яркость краcных светодиодов по отношению к зелёным
#define SIZE_ABC 13 //размер алфавита
#define SIZE_STATUS 4 //размер буфера статуса
#define SIZE_SCREEN 4 //размер буфера экрана
unsigned char buffer [SIZE_SCREEN]; //создаем буфер буфер экрана
uint8_t step = 1; //создаем глобальную переменную подсчёта шагов
// присваиваем имя значению в буфере экрана оно означает цвет светодиода
#define _Red_right_Blue_left buffer[3]
#define _Green buffer[2]
#define _Blue_right_Red_left buffer[1]
#define _RGB buffer[0]
#define _Null memset (buffer, 0, 4) //обнуление буфера экрана
//Алфавит
unsigned char ABC [SIZE_ABC] =
{
0b00001000, //эффект
0b00000100,
0b00000010,
0b00000001,
0b00001001, // для
0b00000101,
0b00000011,
0b00001011,
0b00000111, // поворотника
0b11110000, // разновидности
0b00001111, // стопов
0b00000000, // нет сигнала
};
// конец алфавита
//Массив состояния
unsigned char status [SIZE_STATUS] =
{
0b00001000, /*Состояние эффекта начиная с младшего бита по порядку:
0 Правый поворот
1 Левый поворот
2 Стоп
3 Моргалка
7 Позволяет включить или выключить стоп во время моргания поворотником (взводится при изменении состояния сигнала стоп)*/
1, // Шаг эффекта поворот
1, // Шаг Эффекта моргалка
0b00000000, //Флаги
};
//Массив буфера приёма
unsigned char rx_buf [3] =
{
//Буфер приёма
0b00000000,
0b00000000,
};
int8_t num_rx_buf = 0;
void USART_Init( unsigned int ubrr); //Функция включения USART
void USART_transfer (int8_t a); //Функция передачи по USART
void record (); //прототип функции для записи в сдвиговые регистры
void flash (); //прототип функции мигания поворотниками
void receive (); //функция обработки данных принимаемых по UART
void readmi (uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e); //прототип функции чтения алфавита и записи его в буфер экрана
/*парадигма записи в буфер а=RGB, b=Синий справа-Красный слева, c=Зелёный, d=Красный справа-Синий слева*/
int invert (int8_t b); //прототип функции для инверсии битов в байте
//Обработка прерывания по вектору USART_RX
ISR (USART_RX_vect)
{ rx_buf[num_rx_buf]=UDR0;
num_rx_buf++;
if (num_rx_buf == 2)
{
status[3] |= (1<<0);
num_rx_buf = 0;
}
}
int main (void)
{
TCCR1A = 0b10000011; //устанавливаем настройки таймера
TCCR1B = 0b00001000; //устанавливаем настройки таймера
DDRC = 0b00111111; //устанавливаем необходимые пины порта C на вывод
DDRB = 0b00000110; //устанавливаем необходимые пины порта B на вывод
DDRD = 0b00001100; //устанавливаем необходимые пины порта D на вывод
PORTC |= (1<<1) | (1<<2); //устанавливаем на пинах порта C 1
PORTB &= ~(1<<1) | ~(1<<2); //устанавливаем на пинах порта B 0
PORTD &= ~(1<<2) | ~(1<<3); //устанавливаем на пинах порта D 0
USART_Init(MYUBRR);
_pwm_pass;
_clock_high; //для предотвращения ложного срабатывания
_latch_up; //поднимаем защелку
_flash_G_low; //выключаем светодиоды
_flash_RGB_low; //выключаем светодиоды
_pwm_close_BrRl; //выключаем светодиоды
_pwm_close_RrBl; //выключаем светодиоды
sei(); //разрешаем глобальные прерывания
readmi (11,11,11,11,0); //гасим экран
while (1)
{
uint8_t x;
uint8_t y; //RGB
uint8_t z = 0; //включение и выключение инверсии буфера экрана, 0 справа
uint8_t w; //выбор порта для пропуска PWM на выход
//включение поворотников
if (((status[0] & (7<<0)) == 1) || ((status[0] & (7<<0)) == 2) || ((status[0] & (7<<0)) == 5) || ((status[0] & (7<<0)) == 6))
{
//вкючение правого поворотника
if ((status[0] & (1<<0)) == 1)
{
if (((status[0] & (1<<2)) == 0))
{
x = 11;
y = 11;
z = 0;
w = 1;
}
else //со стопом
{
x = 9;
y = 0;
z = 0;
w = 1;
}
}
//вкючение левого поворотника
else if ((status[0] & (1<<1)) == 2)
{
if (((status[0] & (1<<2)) == 0))
{
x = 11;
y = 11;
z = 1;
w = 2;
}
else //со стопом
{
x = 9;
y = 0;
z = 1;
w = 2;
}
}
_scvagnost;
_pwm_on;
PORTC &= ~(1<<w); //устанавливаем на пине w порта C 0, тем самым пропуская PWM на выход
switch (status[1]) //бегущий огонь
{
case 1:
{
readmi (y, x, 0, 0, z);
status[1] = 2;
_turn_signal_spd;
break;
}
case 2:
{
readmi (y, x, 1, 1, z);
status[1] = 3;
_turn_signal_spd;
break;
};
case 3:
{
readmi (y, x, 2, 2, z);
status[1] = 4;
_turn_signal_spd;
break;
};
case 4:
{
readmi (y, x, 3, 3, z);
status[1] = 5;
_turn_signal_spd;
break;
};
case 5:
{
readmi (y, x, 4, 4, z);
status[1] = 6;
_turn_signal_spd;
break;
};
case 6:
{
readmi (y, x, 5, 5, z);
status[1] = 7;
_turn_signal_spd;
break;
};
case 7:
{
readmi (y, x, 6, 6, z);
status[1] = 8;
_turn_signal_spd;
break;
};
case 8:
{
readmi (y, x, 7, 7, z);
status[1] = 9;
_turn_signal_spd;
break;
};
case 9:
{
readmi (y, x, 8, 8, z);
status[1] = 10;
_turn_signal_spd;
break;
};
case 10:
{
flash();
status[1] = 1;
_turn_signal_spd;
break;
};
}
PORTC |= (1<<w); //устанавливаем на пине w порта C 1
_pwm_off;
}
//включение стопов
else if ((status[0] & (7<<0)) == 4)
{
readmi (3, 9, 11, 10, z);
}
//включение моргалки
else if ((status[0] & (15<<0)) == 8)
{
if (status[2] == 1)
{
readmi (3, 9, 11, 10, z);
status[2] = 2;
_blink_spd;
}
else if (status[2] == 2)
{
readmi (1, 5, 11, 5, 2);
status[2] = 1;
_blink_spd;
}
}
else if ((status[0] & (1<<6)) != 0)
{
readmi (11,11,11,11,0);
status[0] &= ~(1<<6);
}
//обработка принятой инфы, если взведён бит приёма
if (status[3] & (1<<0) != 0)
{
receive ();
}
}
}
void record ()
{
_latch_down; // опускаем защелку
for (int x = 0; x<SIZE_SCREEN; x++) // цикл для переборки байтов в массиве (уточнить как храниться число)
{
for (int y = 7; y>=0; y--) // цикл для перебора битов в байте и подачи их на выход
{
_clock_low; // переводим регистры в режим ожидания данных
if (((buffer[x] & (1<<y)) == 0)^1) // накладываем побитовую маску для считывания нужного бита, ^1 стоит для иверсии бита для отладки (потом нужно будет убрать)
{
_data_0; // если ответ 0, выставляем на входе регистра 0
}
else
{
_data_1; // иначе, выставляем на входе регистра 1
}
_clock_high; // записываем данные в регистр
}
}
_latch_up; // поднимаем защелку, включаем светодиоды
}
void flash () //функция моргания поворотником
{
do
{
if (status[3] & (1<<0) != 0)
{
receive ();
}
if ((status[0] & (1<<7)) == 128) //если было изменение состояния
{
if ((status[0] & (1<<2)) == 4) //если включен стоп добавляем его в эффект
{
if ((status[0] & (1<<0)) == 1)
{
PORTC &= ~(1<<1); //устанавливаем на пине 1 порта C 0, тем самым пропуская PWM на выход
PORTC |= (1<<2); //устанавливаем на пине 1 порта C 1, тем самым не пропуская PWM на выход
readmi (0, 9, 8, 8, 0); // rgb не горит, _Blue_right_Red_left, горят красные, _Green горят 3 правых зеленых, _Red_right_Blue_left горят 3 правых красных
status [0] &= ~(1<<7);
}
else if ((status[0] & (1<<1)) == 2)
{
PORTC &= ~(1<<2); //устанавливаем на пине 2 порта C 0, тем самым пропуская PWM на выход
PORTC |= (1<<1); //устанавливаем на пине 2 порта C 1, тем самым не пропуская PWM на выход
readmi (0, 9, 8, 8, 1); // тоже что и вверху, но инверсное
status [0] &= ~(1<<7);
}
}
//если выключен стоп убираем его из эффекта
else if ((status[0] & (7<<0)) == 2) //если включен левый
{
readmi (11, 11, 8, 8, 1);
status [0] &= ~(1<<7);
}
else if ((status[0] & (7<<0)) == 1) //если включен правый
{
readmi (11, 11, 8, 8, 0);
status [0] &= ~(1<<7);
}
else if ((status[0] & ((1<<7)|(7<<0))) == 128)
{
status [0] &= ~(1<<7);
status [1] = 20;
}
}
_pwm_drop;
_flash_G_hight;
_turn_signal_fsdp;
_pwm_pass;
_flash_G_low;
_turn_signal_fsdp;
status [1]++;
} while (status [1]<20);
}
void readmi (uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e)
{
if (e == 0)
{
buffer [0] = ABC [a];
buffer [1] = ABC [b];
buffer [2] = ABC [c];
buffer [3] = ABC [d];
}
else if (e == 1)
{
buffer [0] = ABC [a];
buffer [3] = ABC [b];
buffer [2] = ABC [c];
buffer [1] = ABC [d];
invert (1);
invert (2);
invert (3);
}
else if (e == 2)
{
buffer [0] = ABC [a];
buffer [3] = ABC [b];
buffer [2] = ABC [c];
buffer [1] = ABC [d];
invert (3);
}
record();
}
int invert (int8_t b)
{
int8_t tmp = buffer [b] & 0xFF;
tmp = ((tmp >> 4) & 15) | ((tmp & 15) << 4);
tmp = ((tmp >> 2) & 51) | ((tmp & 51) << 2);
tmp = ((tmp >> 1) & 85) | ((tmp & 85) << 1);
buffer [b] = buffer [b] & ~0xFF | tmp;
}
void USART_transfer (int8_t a)
{
int8_t x = 0;
do
{
while(!(UCSR0A&(1<<UDRE0)));
if (a == 1)
{
UDR0 = status[0];
}
else
{
UDR0 = 0b00000001;
}
x++;
}
while (x < 2);
}
void USART_Init( unsigned int ubrr)
{
/*установка битрейта */
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr;
UCSR0A = 0; //Режим двойной скорости выключен:
UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0); // Установка параметров: включение портов ввода и вывода, разрешение прерывание по окончанию приёма
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00)|(1<<USBS0); // Установка формата фрейма: 8data, 2stop bit
}
void receive ()
{
if (rx_buf[1] == rx_buf[0])
{
status[0]=rx_buf[1];
USART_transfer (1);
if (status[0] == 0 ||status[0] == 128)
{
status[0] |= (1<<6);
}
}
else
{
USART_transfer (0);
}
status[3] &= ~(1<<0);
}
if ((status[0] & (1<<6)) == 64) //
{
status[0] &= ~(1<<6);
USART_transfer (1);
status[0] &= ~(1<<7);
}
void USART_transfer (int8_t a)
{
int8_t x = 0;
do
{
while(!(UCSR0A&(1<<UDRE0)));
if (a == 1)
{
UDR0 = status[0];
}
else
{
UDR0 = 0b00000001;
}
x++;
}
while (x < 2);
}
//Массив буфера приёма
unsigned char rx_buf [3] =
{
//Буфер приёма
0b00000000,
0b00000000,
};
int8_t num_rx_buf = 0;
//Обработка прерывания по вектору USART_RX
ISR (USART_RX_vect)
{ rx_buf[num_rx_buf]=UDR0;
num_rx_buf++;
if (num_rx_buf == 2)
{
status[3] |= (1<<0);
num_rx_buf = 0;
}
}
//обработка принятой инфы, если взведён бит приёма
if (status[3] & (1<<0) != 0)
{
receive ();
}
void receive ()
{
if (rx_buf[1] == rx_buf[0])
{
status[0]=rx_buf[1];
USART_transfer (1);
if (status[0] == 0 ||status[0] == 128)
{
status[0] |= (1<<6);
}
}
else
{
USART_transfer (0);
}
status[3] &= ~(1<<0);
}
void USART_transfer (int8_t a)
{
int8_t x = 0;
int8_t temp = status[0];
do
{
if (x==1)
{
temp = temp ^ 0xFF;
}
while(!(UCSR0A&(1<<UDRE0)));
if (a == 1)
{
UDR0 = temp;
}
else
{
UDR0 = 0b00000001;
}
x++;
}
while (x < 2);
}
void receive ()
{
int8_t temp = rx_buf[1] & rx_buf[0];
if (temp == 0)
{
status[0]=rx_buf[0];
USART_transfer (1);
if (status[0] == 0 ||status[0] == 128)
{
status[0] |= (1<<6);
}
}
else
{
USART_transfer (0);
}
status[3] &= ~(1<<0);
}
A | B | A XOR B |
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 0 |
Цитата: Slabovik от 08 Нояб., 2021, 18:19Второй байт можно несколько видоизменить (с целью небольшого повышения степени обнаружения ошибки), например, поксорить с 0FFh (простая инверсия бит), а на принимающей стороне в качестве проверки поксорить между собой оба принятых байта. Если результат будет 0,
//имена бит в массиве состояния
#define RXEND 2
#define STOP 2
#define LEFT 1
#define RIGHT 0
#define BLINK 3
#define RTFG 0
#define LTFG 0
#define STCE 7
#define OFF 6
...
...
//Массив состояния
unsigned char status [SIZE_STATUS] =
{
0b00001000, /*Состояние эффекта начиная с младшего бита по порядку:
0 Правый поворот, имя бита RIGHT
1 Левый поворот, имя бита LEFT
2 Стоп, имя бита STOP
3 Моргалка, имя бита BLINK
7 Позволяет включить или выключить стоп во время моргания поворотником (взводится при изменении состояния сигнала стоп) STCE*/
1, // Шаг эффекта поворот
1, // Шаг Эффекта моргалка
0b00000000, /* Флаги :
0 Правый поворот вкл (нужен для сброса шага эффекта после выключения)
1 Левый поворот вкл
2 Пакет принят*/
};
...
...
if ((status[0] & (1<<STCE)) != 0)
{
if ((status[0] & 3)^(status[3] & 3) != 0)
{
int8_t temp = (status[0] & 3);
status[3] &= ~3;
status[3] = (status[3] | temp);
status[1] = 1;
}
if ((status[3]& 3) == 2) // добавлено для дебага
{
PORTD ^= (1<<4);
}
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./avrblink2.elf...done.
(gdb) target remote localhost:1200
Remote debugging using localhost:1200
0x00000000 in __vectors ()
(gdb) load
Loading section .text, size 0x600 lma 0x0
Loading section .data, size 0x12 lma 0x600
Start address 0x0, load size 1554
Transfer rate: 505 KB/sec, 518 bytes/write.
(gdb) break 158
Breakpoint 1 at 0x3e4: file /home/shaman/.bind/Sklad/Svalka/Фонарь/Код/avrblink2.c, line 158.
(gdb) distlay/t status
Undefined command: "distlay". Try "help".
(gdb) display/t status
1: /t status = {10101010, 10101010, 10101010, 10101010}
(gdb) continue
Continuing.
Breakpoint 1, main () at /home/shaman/.bind/Sklad/Svalka/Фонарь/Код/avrblink2.c:158
158 if ((status[0] & (1<<STCE)) != 0)
1: /t status = {10000001, 1, 1, 0}
(gdb) step
160 if ((status[0] & 3)^(status[3] & 3) != 0) // баг становиться равной 0 только при нажатии в право
1: /t status = {10000001, 1, 1, 0}
(gdb) step
164 status[3] = (status[3] | temp);
1: /t status = {10000001, 1, 1, 0}
(gdb) step
167 status[1] = 1;
1: /t status = {10000001, 1, 1, 1}
(gdb) step
171 if ((status[3]& 3) == 2)
1: /t status = {10000001, 1, 1, 1}
(gdb) continue
Continuing.
Breakpoint 1, main () at /home/shaman/.bind/Sklad/Svalka/Фонарь/Код/avrblink2.c:158
158 if ((status[0] & (1<<STCE)) != 0)
1: /t status = {10000001, 10, 1, 1}
(gdb) step
160 if ((status[0] & 3)^(status[3] & 3) != 0) // баг становиться равной 0 только при нажатии в право
1: /t status = {10000001, 10, 1, 1}
(gdb) step
171 if ((status[3]& 3) == 2)
1: /t status = {10000001, 10, 1, 1}
(gdb)
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./avrblink2.elf...done.
(gdb) target remote localhost:1200
Remote debugging using localhost:1200
0x00000000 in __vectors ()
(gdb) load
Loading section .text, size 0x600 lma 0x0
Loading section .data, size 0x12 lma 0x600
Start address 0x0, load size 1554
Transfer rate: 505 KB/sec, 518 bytes/write.
(gdb) break 158
Breakpoint 1 at 0x3e4: file /home/shaman/.bind/Sklad/Svalka/Фонарь/Код/avrblink2.c, line 158.
(gdb) display/t status
1: /t status = {10101010, 10101010, 10101010, 10101010}
(gdb) continue
Continuing.
Breakpoint 1, main ()
at /home/shaman/.bind/Sklad/Svalka/Фонарь/Код/avrblink2.c:158
158 if ((status[0] & (1<<STCE)) != 0)
1: /t status = {10000010, 1, 1, 0}
(gdb) step
160 if ((status[0] & 3)^(status[3] & 3) != 0) // баг становиться равной 0 только при нажатии в право
1: /t status = {10000010, 1, 1, 0}
(gdb) step
164 status[3] = (status[3] | temp);
1: /t status = {10000010, 1, 1, 0}
(gdb) step
167 status[1] = 1;
1: /t status = {10000010, 1, 1, 10}
(gdb) step
171 if ((status[3]& 3) == 2)
1: /t status = {10000010, 1, 1, 10}
(gdb) continue
Continuing.
Breakpoint 1, main ()
at /home/shaman/.bind/Sklad/Svalka/Фонарь/Код/avrblink2.c:158
158 if ((status[0] & (1<<STCE)) != 0)
1: /t status = {10000010, 10, 1, 10}
(gdb) step
160 if ((status[0] & 3)^(status[3] & 3) != 0) // баг становиться равной 0 только при нажатии в право
1: /t status = {10000010, 10, 1, 10}
(gdb) step
164 status[3] = (status[3] | temp);
1: /t status = {10000010, 10, 1, 10}
(gdb)
Цитата: Slabovik от 23 Нояб., 2021, 20:18Я правильно понимаю, что если два младших (не последних !) бита различаются, то нужно выполнить операции?Да правильно. Говорила мама учи математику... Вынес 3-ку за скобки, вот так: if (((status[0] ^ status[3]) & 3) != 0), заработало.
Цитата: Slabovik от 26 Нояб., 2021, 15:21Ага, ну значит дело действительно было в интерпретации компилятором приоритетов операций. Мы думаем так, а компилятор работает не так :) Расстановка скобок дала прямое указание компилятору делать в нужном нам порядке :)Ну да, так тоже работает if (((status[0]& 3)^(status[3] & 3)) != 0)