Jump to content

    

Обращение к битам в массиве через <<

Доброго времени суток

есть ряд включенных последовательно 74hc165 из которых их состояния записываются в массив

каким образом организовать сквозное обращение к битам?

имею примерно следующее

#define PD_PROTECT		0	//PD PROTECT
#define HI_TEMP			1	//HI TEMP
#define HI_CURRENT_PR	2	//HI Current PROTECT
#define ALARM_ALL		3	//Защита общая
#define PWR_DN			4	//Провал питания
#define PWR_UP			5	//Превышеие сети
#define SHORT_CURCUIT_LED 6	//сигнал КЗ с блока ШИММа
#define PROTECT_TIME	7	//Задержка таймера ШИМа
#define AUTO_CUTTER		8	//подключен резак для автоматической резки
#define KT2_TEN			9	//Термореле тена
#define KT4_LEVEL		10	//Датчик уровня жидкости
#define KT3_Water		11	//Датчик потока
#define HAND_CUTTER		12	//Подключен резак для ручной резки
#define TRAILER_CUTTER	13	//Концевик
#define BUTTON_CUTTER	14	//Кнопка плазмотрона
#define SHORT_CURCUIT	15	//Короткое замыкание

пытаюсь обращаться вот так

uint8_t data[3];
#define IS(x) (int)data[1] & (int)(1<<x)

в итоге к старшей микросхеме доступ есть а вот ко второй уже нет

Share this post


Link to post
Share on other sites

Ткни пальцем, где тут обращение к микросхемам?

Share this post


Link to post
Share on other sites

массив заполняется данными в другом месте. микрухи подключены по SPI и обрабатываются вот таким куском кода

#include <avr/delay.h>
#include <avr/interrupt.h>
#include "SPI.h"
#include "Periph.h"

uint8_t SPI_write[SPI_WRITE_SIZE_ARRAY];
uint8_t SPI_read[SPI_READ_SIZE_ARRAY];
uint8_t pointer = 0;
  
void SPI_Init(void)
{
   SPI_DDRX |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO);
   SPI_PORTX &= ~(1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO);

   SPCR=(
   (1<<SPIE)//Разрешить прерывания от SPI
   |(1<<SPE)//Включить модуль SPI
   |(1<<DORD)//Младший бит вперед
   |(1<<MSTR)//SPI в режиме Мастер
   );
   
   SPSR |= (1<<SPI2X);	
}

void SPI_StartWrite(void)
{
	SPI_PORTX &= ~(1<<SPI_SS);
	
	_delay_ms(1);
	
	SPI_PORTX |= (1<<SPI_SS);
	
	pointer = 0;
	
	SPDR = SPI_write[pointer];
}

ISR(SPI_STC_vect)
{
	//прерывание по завершению передачи байта
	
	if(pointer < SPI_READ_SIZE_ARRAY)
		SPI_read[pointer] = SPDR;
	
	pointer++;
	
	if(pointer >= SPI_WRITE_SIZE_ARRAY)
		return;
	
	SPDR = SPI_write[pointer];
}

 

Share this post


Link to post
Share on other sites
1 час назад, Reystlin сказал:

#define IS(x) (int)data[1] & (int)(1<<x)

 

#define IS(x) (data[(x) >> 3] & (1 << ((x) & 0x07)))

 

 

Share this post


Link to post
Share on other sites
1 час назад, Reystlin сказал:

есть ряд включенных последовательно 74hc165 из которых их состояния записываются в массив

каким образом организовать сквозное обращение к битам?


#define SHORT_CURCUIT	15	//Короткое замыкание

пытаюсь обращаться вот так


uint8_t data[3];
#define IS(x) (int)data[1] & (int)(1<<x)

в итоге к старшей микросхеме доступ есть а вот ко второй уже нет

Вам надо из общего номера бита вычислить номер байта в массиве и номер бита в этом байте. Номер байта равен номеру бита делённому на 8, а номер бита - остатку от этого деления. Типа так:

uint8_t data[3];
#define IS(x) data[x/8] & (1<<(x%8))

 

Share this post


Link to post
Share on other sites
54 минуты назад, AHTOXA сказал:

Вам надо из общего номера бита вычислить номер байта в массиве и номер бита в этом байте.

Можно всей этой битовой арифметикой не пользоваться, если научиться пользоваться структурами.

Примерно так (бит данных 16, зачем 3 байта?)

Можно легко добавлять, удалять, смещать, менять порядок бит, не навлекая проблем магических чисел.

typedef struct s_s
{
	union
	{
		BYTE	data[3];
		struct
		{
			BYTE PD_PROTECT:1;				//PD PROTECT
			BYTE HI_TEMP:1;						//HI TEMP
			BYTE HI_CURRENT_PR:1;			//HI Current PROTECT
			BYTE ALARM_ALL:1;					//Защита общая
			BYTE PWR_DN:1;						//Провал питания
			BYTE PWR_UP:1;						//Превышеие сети
			BYTE SHORT_CURCUIT_LED:1;	//сигнал КЗ с блока ШИММа
			BYTE PROTECT_TIME:1;			//Задержка таймера ШИМа

			BYTE AUTO_CUTTER:1;				//подключен резак для автоматической резки
			BYTE KT2_TEN:1;						//Термореле тена
			BYTE KT4_LEVEL:1;					//Датчик уровня жидкости
			BYTE KT3_Water:1;					//Датчик потока
			BYTE HAND_CUTTER:1;				//Подключен резак для ручной резки
			BYTE TRAILER_CUTTER:1;		//Концевик
			BYTE BUTTON_CUTTER:1;			//Кнопка плазмотрона
			BYTE SHORT_CURCUIT:1;			//Короткое замыкание
			
			BYTE some;			
		};
	};
} s_s;

s_s	h;

void foo(void)
{
	h.AUTO_CUTTER = 1;
	h.BUTTON_CUTTER = 0;
	
	SPDR = h.data[pointer];
}

 

Share this post


Link to post
Share on other sites

на 3 кнопки висят и обрабатываются отдельно.

да, интересное решение:) спасибо

Share this post


Link to post
Share on other sites
3 минуты назад, adnega сказал:

Можно всей этой битовой арифметикой не пользоваться, если научиться пользоваться структурами.

Ага, только это решение будет зависеть от порядка байтов в слове. А после этого всё равно будет передавать эту структуру побайтно:)

Share this post


Link to post
Share on other sites
2 минуты назад, AHTOXA сказал:

Ага, только это решение будет зависеть от порядка байтов в слове.

На уровне

	SPDR = h.data[pointer];

легко корректируется (т.е. в одном месте конкретного драйвера).

Либо на уровне описания структуры.

2 минуты назад, AHTOXA сказал:

А после этого всё равно будет передавать эту структуру побайтно:)

Можно передать хоть через указатель и DMA: структура - это просто память.

Share this post


Link to post
Share on other sites
57 минут назад, adnega сказал:

На уровне


	SPDR = h.data[pointer];

легко корректируется (т.е. в одном месте конкретного драйвера). 

Либо на уровне описания структуры. 

Да, исправить несложно. Но универсального исходника для разных контроллеров уже не выйдет. Плюс к тому могут быть сложности с полями из нескольких битов, если они лежат на стыке байтов (часть поля в одном байте, часть в соседнем). В общем, выглядит красиво, но в реальности есть нюансы.

И ещё один момент. Попробуйте с ходу найти в своём описании бит номер 12 :) Да, вы их сгруппировали по 8, но это всё по ходу работы может съехать:)

 

В общем, я одно время был в восторге от этого решения, и применял его везде, но потом постепенно отказался.

Share this post


Link to post
Share on other sites
2 минуты назад, AHTOXA сказал:

Да, исправить несложно. Но универсального исходника для разных контроллеров уже не выйдет.

В профиле Cortex-M, вроде, только LE-порядок байт возможен. Там, где есть реальное железо, и внутреннее представление играет роль - нужно применять конкретику, т.к. на абстракциях уже решать не возможно. Переносимость исходника LE<>BE нужно описывать специальным образом.

2 минуты назад, AHTOXA сказал:

Плюс к тому могут быть сложности с полями из нескольких битов, если они лежат на стыке байтов (часть поля в одном байте, часть в соседнем).

Можно бороть через расширение длины (типа DWORD some:1), а в тяжелых случаях - через union.

2 минуты назад, AHTOXA сказал:

В общем, выглядит красиво, но в реальности есть нюансы.

С магическими числами нюансов больше. Разве нет?

А попробуйте задать не тот номер в define? А попробуйте установить 12 бит, которого в байте просто нет? А если за границу массива после этого вылезли?

Нужно помнить размеры всех массивов? А если добавили еще одно поле и размеры массивов стали больше? Все исходники править вручную?

2 минуты назад, AHTOXA сказал:

И ещё один момент. Попробуйте с ходу найти в своём описании бит номер 12 :) Да, вы их сгруппировали по 8, но это всё по ходу работы может съехать:)

В том-то и суть, что имеет место переход от магического числа 12 к названию бита.

Это

HAND_CUTTER

, а с каким он будет номером - все-равно без дополнительной документации смысла не имеет.

Применение структур дает еще один существенный плюс, что код получается читаемый. Кста, он в итоге разворачивается в биты и маски, но без использования define.

Структуры - очень мощный инструмент, и если его применять, то где, как ни в таких задачах?

Упс: тут AVR

20 минут назад, AHTOXA сказал:

В общем, я одно время был в восторге от этого решения, и применял его везде, но потом постепенно отказался.

В пользу чего? И почему? Очень интересно знать.

Share this post


Link to post
Share on other sites
8 часов назад, adnega сказал:

В профиле Cortex-M, вроде, только LE-порядок байт возможен.

А вот маленький STM8 неожиданно оказался BE. Это, кстати, было одной из причин того, что я пересмотрел свой подход. Я понял, что есть живые "большие индейцы".

8 часов назад, adnega сказал:

С магическими числами нюансов больше. Разве нет? 

Зачем сразу магические числа? Объявим в одном месте константу, и будем её использовать. Если HAND_CUTTER - это 12 бит в слове, то определение

static constexpr size_t HAND_CUTTER { 12 };

будет однозначным и легко поддерживаемым.

8 часов назад, adnega сказал:

В том-то и суть, что имеет место переход от магического числа 12 к названию бита. 

Но ведь нам нужно, чтобы этот HAND_CUTTER был именно на 12 ноге сдвигового регистра! Ведь мы же не хотим вместо отрезания рук прострелить себе ногу? :)

8 часов назад, adnega сказал:

В пользу чего? И почему? Очень интересно знать.

Сдвиги и маски. По возможности заворачиваю в шаблонные классы. Почему - вроде описал уже.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this