Ярлыки

_GetPixelIndex (1) _SetPixelIndex (1) 3-phase (1) 800x480 (1) АЦП (1) генератор (1) синхронный усилитель (2) структура (1) учебный курс (1) шаговый двигатель (1) ШИМ (2) accert (1) AD7608 (1) AD8429 (1) ADC (5) amplifer (1) arccos (1) arcsin (1) arctang (2) arctg (3) ARM (2) arm_sqrt_q15 (2) assembler (6) ASSERT (1) atan (2) bit (1) Bitband (1) boot (3) bootlloader (1) BUTTON (1) C (5) C# (1) CAN (2) CC2530 (5) CMSIS (4) command (1) Cordic (1) Core746I (1) CubeMX (4) DBGMCU (2) debug (2) debug.ini (1) delegate (1) Digital Potentiometers (1) DigitalPOT (1) Discovery (1) DMA (9) DMA2D (1) DSP (1) DSP library (1) DWT (1) EFM32 (5) EmWin (9) EXTI (1) FATFS (1) FMC (2) FreeRTOS (2) gl868-dual cmux (1) GPIO (4) GUI (2) GUIBuilder (1) GUIDRV_CompactColor_16 (1) HAL (3) HappyGecko (1) Hard Fault (2) heap (1) I2C (1) ID (1) ILI9320 (1) ILI9325 (1) Initialisation (1) InitLTDC (1) Instrumentithion (1) Interrupt (4) ITR (1) JTAG (1) Keil (5) LCDConf (2) lock-in (1) LTCD (1) LTDC (3) main (1) memory (1) MINI_STM32 Revision 01 (1) nBoot0 (1) NVIC (1) OnePulse (2) OSAL (4) pack (1) phase (1) printf (3) Pulse (1) PWM (12) RCC (2) RCR (1) Register (1) RESET (2) RS232 (3) RSS (1) RTC (3) RTOS-RTX (1) RTT (1) RTX-RTOS (1) SDCard (1) SDRAM (6) Segger (2) SPI (3) sqrt (3) SSD1298 (1) SSD1963 (1) Standart Peripherial Library (3) STANDBAY (1) startup (1) STemWin (8) stepper motor (1) STlink (2) STM32 (17) STM32429ZI (1) STM32Cube (1) STM32DBG.IN (1) STM32F (28) STM32F0 (4) STM32F1 (13) STM32F4 (10) STM32F4 Discovery (1) STM32F407ZG (1) STM32F429 (2) STM32F746 (1) STOP (1) string (1) struct (1) SWD (1) SWD JTAG (1) Synhronization (1) system_stm32f4xx.c (1) SystemInit (1) SysTick (1) task (4) telit (1) TIM (27) typedef (1) UART (1) USART (9) viewer (2) WM_PAINT (1) Z-stack (5) ZigBee (5)

воскресенье, 21 декабря 2014 г.

Битовые операции C

Во встраиваемых системах часто для экономии памяти приходится использовать битовые операции, например для реализации флага какого-либо события. Далее рассмотрен удобный способ работы с битами на макросах.
Для начала создадим макрос для объявления битовых массивов:
typedef uint8_t BARR_ELTYPE;
#define BARR_ELBITS 8
#define BARR_ARRAYSIZE(N) ((N + BARR_ELBITS - 1) / BARR_ELBITS)
Так, для того чтобы создать, массив из 14 бит:
BARR_ELBITS arr_bit(BARR_ARRAYSIZE(N))
14 бит — это 2 байта без 2 бит. Определение количества байт идет путем деления количества байт(N) на количество байт в одной переменной(BARR_ELBITS) и округления значения в большую сторону. Для округления используется формула (A + B — 1) / B. Данная формула верна если A и B не отрицательны и A + B не создает переполнения.
Теперь создадим макросы для изменения состояния битов и их проверки.
#define BARR_ELMUM(N) (N / BARR_ELBITS)
#define BARR_BITNUM(N) (N % BARR_ELBITS)
#define BARR_SET(barr, N) ( barr[BARR_ELMUM(N)] |= ( (BARR_ELTYPE)1 << BARR_BITNUM(N) ) )
#define BARR_CLEAR(barr, N) ( barr[BARR_ELMUM(N)] &= ( ~( (BARR_ELTYPE)1 << BARR_BITNUM(N) ) ) )
#define BARR_INV(barr, N) (barr[BARR_ELMUM(N)] ^= ( (BARR_ELTYPE)1 << BARR_BITNUM(N) ))
#define BARR_TEST(barr, N) (barr[BARR_ELMUM(N)] & ( (BARR_ELTYPE)1 << BARR_BITNUM(N) ))
BARR_ELMUM — используется для определения элемента(байта) в котором находится бит, путем деления без остатка.
BARR_BITNUM — используется для определения позиции бита в элементе(байте), путем деления и взятия остатка.
BARR_SET и BARR_CLEAR — соответственно устанавливают и сбрасывают нужный бит в битовом массиве. Для этого они используют битовое «ИЛИ» и «И» с 1 и 0 в нужном разряде соответственно.
BARR_INV — инвертирует нужный бит. Для этого используется битовое исключающее «ИЛИ» с 1.
BARR_TEST — проверяет установлен ли нужный бит в 1 или нет. Если установлен, то возвращает не 0 (именно не 0, а не 1).
Пример:
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;

typedef uint8_t  BARR_ELTYPE;
#define BARR_ELBITS 8
#define BARR_ARRAYSIZE(N) ((N + BARR_ELBITS - 1) / BARR_ELBITS)

#define BARR_ELMUM(N) (N / BARR_ELBITS)
#define BARR_BITNUM(N) (N % BARR_ELBITS)
#define BARR_SET(barr, N) ( barr[BARR_ELMUM(N)] |= ( (BARR_ELTYPE)1 << BARR_BITNUM(N) ) )
#define BARR_CLEAR(barr, N) ( barr[BARR_ELMUM(N)] &= ( ~( (BARR_ELTYPE)1 << BARR_BITNUM(N) ) ) )
#define BARR_INV(barr, N) (barr[BARR_ELMUM(N)] ^= ( (BARR_ELTYPE)1 << BARR_BITNUM(N) ))
#define BARR_TEST(barr, N) (barr[BARR_ELMUM(N)] & ( (BARR_ELTYPE)1 << BARR_BITNUM(N) ))


BARR_ELTYPE arr_bit[BARR_ARRAYSIZE(16)];

void main(void)
{
    BARR_SET(arr_bit, 0);
    BARR_SET(arr_bit, 1);
    BARR_CLEAR(arr_bit, 4);
    BARR_CLEAR(arr_bit, 1);
    BARR_INV(arr_bit, 1);
    
    printf("%d \n", arr_bit[0]);    
    if(BARR_TEST(arr_bit, 0) != 0)
    {
        printf("%d \n", sizeof(arr_bit));
    }
}


Noteпомнить
Таблица истиности ^
 x1 x2 res
1  1  0
1  0  1
0  1  1
0  0  0 
Тогда когда ^ с 1, то всегда происходит изменение состояния.
Если с 0, то нет изменения состояния.
 x = (x ^ (1<<n)) // изменение состояния n-го бита переменной x
Для определения члена массива и номера байта которого надо изменить состояние можно использовать такую конструкцию:
amt_net_temp = work_buf_trans / 8; // определили какой член массива
amt_net_temp_2 = work_buf_trans % 8; // определили какой бит

// меняем состояние
f_busy_buf[amt_net_temp] = (f_busy_buf[amt_net_temp] ^ (1<<amt_net_temp_2));

Комментариев нет:

Отправить комментарий