Вс авг 14, 2022 20:35:05
result |= ((DDRB & (1<<Rbit)) >> Rbit) << Wbit;
result = (DDRB & (1 << Rbit)) ? result | (1 << Wbit) : result & ~(1 << Wbit);
Вс авг 14, 2022 20:49:21
Что, проще нет что ли? Давайте предоставим все это компилятору.MLX90640 писал(а):Тут сложность в понимании того, что используется так называемый тренарный оператор условия.
union BytByte {
struct {
unsigned char b0: 1;
unsigned char b1: 1;
unsigned char b2: 1;
unsigned char b3: 1;
unsigned char b4: 1;
unsigned char b5: 1;
unsigned char b6: 1;
unsigned char b7: 1;
} bit;
volatile uint8_t byte;
}__attribute__((packed));
union BytByte myBByte;
union BytByte rezultat;
myBByte.byte = DDRB;
rezultat.bit.b0 = myBByte.bit.b1;
rezultat.bit.b7= myBByte.bit.b0;
rezultat.bit.b1 = myBByte.bit.b2;
// и так далее
rezultat.byte // здесь будет результат
Вс авг 14, 2022 21:10:12
Вс авг 14, 2022 23:02:29
Вс авг 14, 2022 23:07:51
Ср авг 17, 2022 13:11:54
Ср авг 17, 2022 13:40:37
Ср авг 17, 2022 14:42:08
Второй из них заключается в том, чтобы при сдвиге цифр влево просто переносить байты цифр в буфере дисплея левее, начиная слева. Допустим, есть буфер
buf[4], в котором buf[0] - самый левый разряд, а buf[3] - самый правый. Так вот, каждый шаг анимации бегущей строки будет представлен шагами:
Первый же способ делается на указателях. В этом случае ничего не копируется, инкрементируется только указатель на начало отображения строки в дисплей, сдвигаясь по строке.
ISR(TIMER1_COMPA_vect) { //обработчик прерывания по совпадению А таймера 1, счетчик сбрасывается в 0
PORTD&=0b11110000; // потушить все (разряды - off)
PORTB=digits[digit_out[cur_dig]]&maska; // символ на экран
PORTD |= (1<<cur_dig); // засветить нужный разряд (бит знакоместа - on)
cur_dig++; if (cur_dig > 3) {
cur_dig = 0;
}
}
Ср авг 17, 2022 15:15:29
/* кодирование сегментов в байте */
#define SEG_A (1 << 0)
#define SEG_B (1 << 1)
#define SEG_C (1 << 2)
#define SEG_D (1 << 3)
#define SEG_E (1 << 4)
#define SEG_F (1 << 5)
#define SEG_G (1 << 6)
#define SEG_dp (1 << 7)
/* символы шрифта */
#define BLANK 0
#define CH_0 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F )
#define CH_1 ( SEG_B | SEG_C )
#define CH_2 (SEG_A | SEG_B | SEG_D | SEG_E | SEG_G)
#define CH_3 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_G)
#define CH_4 ( SEG_B | SEG_C | SEG_F | SEG_G)
#define CH_5 (SEG_A | SEG_C | SEG_D | SEG_F | SEG_G)
#define CH_6 (SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)
#define CH_7 (SEG_A | SEG_B | SEG_C )
#define CH_8 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)
#define CH_9 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G)
#define CH_DASH ( SEG_G)
#define CH_DNDASH ( SEG_D )
const uint8_t font[] =
{CH_0, CH_1, CH_2, CH_3, CH_4, CH_5, CH_6, CH_7, CH_8, CH_9};
#define NUM_DIG 4 // число разрядов в индикаторе
static uint8_t buf[NUM_DIG]; // буфер хранения данных о сегментах в разрядах
/** ----------
* @brief Преобразование текстовой строки в данные для сегментов
* индикатора.
* @param *str - входная текстовая строка в кодировке ANSI
* @param len - длина строки
*/
void DND_Print(char *str, uint8_t len)
{
uint8_t digit = 0;
uint8_t dotsign[NUM_DIG] = {0, 0, 0, 0};
/* преобразование текстовой строки */
while(len--)
{
switch(*str){
/* цифры */
case '0' ... '9':
buf[digit] = font[*str - '0'];
break;
/* тире */
case '-': buf[digit] = CH_DASH;
break;
case '_': buf[digit] = CH_DNDASH;
break;
/* десятичные точки*/
case '.':
case ',':
/* для индикатора с разделительным двоеточием */
if(digit == 2)
{
dotsign[3] = SEG_dp;
}
digit--;
break;
/* разделительные точки */
case ':':
/* для индикатора с разделительным двоеточием */
if(digit == 2)
{
dotsign[2] = SEG_dp;
dotsign[3] = SEG_dp;
}
digit--;
break;
default: buf[digit] = BLANK;
}
str++; // следующий символ в строке
digit++; // следующий разряд
if(digit > NUM_DIG) break;
}
/* добавление признака точек в разряды*/
for(digit = 0; digit < NUM_DIG; digit++)
{
buf[digit] |= dotsign[digit];
}
}
/** ----------
* @brief Поразрядное переключение шагов динамической индикации.
*/
#ifdef USE_SEGMENT_ANIMATION
#include "fx.h"
#endif
void DND_DynaScan(void)
{
static uint8_t digit = 0;
#ifdef USE_SEGMENT_ANIMATION
uint8_t mask;
mask = DND_SegAnimation_GetMask(digit);
DND_DigitOut(digit, buf[digit] & mask);
#else
DND_DigitOut(digit, buf[digit]); // для варианта без анимации сегментов
#endif
digit++;
if(digit >= NUM_DIG) digit = 0;
}
DND_Print("1259", 4); // фиксированная текстовая строка в формате ANSI
char str[10];
uint8_t len;
len = sprintf(str, "%02d:%02d", current_time.tm_hour, current_time.tm_min);
DND_Print(str, len);
/* кодирование сегментов для цифр такое же как выше */
const uint8_t font[] =
{CH_0, CH_1, CH_2, CH_3, CH_4, CH_5, CH_6, CH_7, CH_8, CH_9};
/* Преобразование чисел от 0 до 9 в сегменты индикатора */
void DND_Print(byte d0, byte d1, byte d2, byte d3)
{
buf[0] = font[d0];
buf[1] = font[d1];
buf[2] = font[d2];
buf[3] = font[d3];
}
Ср авг 17, 2022 15:16:54
Ср авг 17, 2022 15:18:55
Чт авг 18, 2022 03:43:58
Чт авг 18, 2022 09:52:52
Да... Если всё написанное выше слишком сложно для понимания, то можно существенно упростить функции, сделав их по-топорному,
Чт авг 18, 2022 13:08:33
Чт авг 18, 2022 13:57:45
#define SEG_A (1 << 5)
#define SEG_B (1 << 7)
#define SEG_C (1 << 0)
#define SEG_D (1 << 3)
#define SEG_E (1 << 1)
#define SEG_F (1 << 4)
#define SEG_G (1 << 6)
#define SEG_dp (1 << 2)
//Setup
#define DisablePWM //отключение ШИМ выходов (мне для протеуса)
#define EnDebug //включение порта отладки (reset) мне для протеуса
//полярность дисплеев
#define DISPLAY_U_CC //#define DISPLAY_U_CA или #define DISPLAY_U_CC при отсутствии - автоопределение
#define DISPLAY_I_CC //#define DISPLAY_I_CA или #define DISPLAY_I_CC при отсутствии - автоопределение
//соответствие сегмента и номера ноги порта D
#define Seg_A 5 //0
#define Seg_B 0 //1
#define Seg_C 1 //2
#define Seg_D 6 //3
#define Seg_E 7 //4
#define Seg_F 2 //5
#define Seg_G 3 //6
#define Seg_P 4 //7
//#define ShowLogo //показать лого
..........
..........
//Digits
//Описание цифр семисегментного индикатора и функции, связанные с экраном
//расстановка единиц в маске
#define _A_ (1<<Seg_A)
#define _B_ (1<<Seg_B)
#define _C_ (1<<Seg_C)
#define _D_ (1<<Seg_D)
#define _E_ (1<<Seg_E)
#define _F_ (1<<Seg_F)
#define _G_ (1<<Seg_G)
#define _P_ (1<<Seg_P)
#define ___ (0 )
//знакогенератор
#define _0 (_A_|_B_|_C_|_D_|_E_|_F_|___)
#define _1 (___|_B_|_C_|___|___|___|___)
#define _2 (_A_|_B_|___|_D_|_E_|___|_G_)
#define _3 (_A_|_B_|_C_|_D_|___|___|_G_)
#define _4 (___|_B_|_C_|___|___|_F_|_G_)
#define _5 (_A_|___|_C_|_D_|___|_F_|_G_)
#define _6 (_A_|___|_C_|_D_|_E_|_F_|_G_)
#define _7 (_A_|_B_|_C_|___|___|___|___)
#define _8 (_A_|_B_|_C_|_D_|_E_|_F_|_G_)
#define _9 (_A_|_B_|_C_|_D_|___|_F_|_G_)
#define _A (_A_|_B_|_C_|___|_E_|_F_|_G_)
#define _B (___|___|_C_|_D_|_E_|_F_|_G_)
#define _c (___|___|___|_D_|_E_|___|_G_)
#define _C (_A_|___|___|_D_|_E_|_F_|___)
#define _D (___|_B_|_C_|_D_|_E_|___|_G_)
#define _E (_A_|___|___|_D_|_E_|_F_|_G_)
#define _F (_A_|___|___|___|_E_|_F_|_G_)
#define _G (_A_|_B_|___|___|___|_F_|_G_) //°
#define _U (___|_B_|_C_|_D_|_E_|_F_|___)
#define _t (___|___|___|_D_|_E_|_F_|_G_)
#define _P (_A_|_B_|___|___|_E_|_F_|_G_)
#define _r (___|___|___|___|_E_|___|_G_)
#define _o (___|___|_C_|_D_|_E_|___|_G_)
#define _n (___|___|_C_|___|_E_|___|_G_)
#define _Z (___|___|___|___|___|___|___) //выкюченный разряд
#define _N (___|___|___|___|___|___|_G_) // "-"
const unsigned char DIG[]={_0,_1,_2,_3,_4,_5,_6,_7,_8,_9};
//flash unsigned char DIG[]={_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_a,_b,_C,_d,_e,_f};
#if (defined(DISPLAY_U_CC) && defined(DISPLAY_U_CA))
#error "Conflict on DISPLAY_U mode"
#endif
#if (defined(DISPLAY_I_CC) && defined(DISPLAY_I_CA))
#error "Conflict on DISPLAY_I mode"
#endif
.......
.......
Чт авг 18, 2022 13:59:03
switch(*str){
/* цифры */
case '0' ... '9':
buf[digit] = font[*str - '0'];
break;
#ifdef USE_LETTERS
/* буквы */
case 'A' ... 'U':
buf[digit] = font[*str - 'A' + 10];
break;
case 'a' ... 'u':
buf[digit] = font[*str - 'a' + 10];
break;
#endif
/* тире */
case '-': buf[digit] = CH_DASH;
break;
case '_': buf[digit] = CH_DNDASH;
break;
/* десятичные точки*/
case '.':
case ',':
/* для индикатора с разделительным двоеточием */
if(digit == 2)
{
dotsign[3] = SEG_dp;
}
digit--;
break;
/* разделительные точки */
case ':':
/* для индикатора с разделительным двоеточием */
if(digit == 2)
{
dotsign[2] = SEG_dp;
dotsign[3] = SEG_dp;
}
digit--;
break;
default: buf[digit] = BLANK;
Чт авг 18, 2022 15:53:02
Функция void DND_Print(byte d0, byte d1, byte d2, byte d3) принимает числовые значения d0, d1, d2, d3
Чт авг 18, 2022 16:20:03
#define byte unsigned char
Чт авг 18, 2022 17:15:38
Чт авг 18, 2022 17:39:16