Страница 1 из 2

Динамическая индикация на 74HC595

Добавлено: Ср ноя 15, 2017 03:52:41
7seg
Запускаю симуляцию в протеусе динамическая индикация отображается "кракозябрами"(раньше дин.индикация всегда отображалась в протеусе корректно).

Вот и закралась мысль ко мне может я чего то не знаю ?(
Может кто подсказать где кроется ошибка?
Схема:
СпойлерИзображение
Фулл код
Спойлер

Код: Выделить всё

#define F_CPU 8000000UL

#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>

volatile uint8_t TEST=10;

#define SPI_PORT PORTB
#define SPI_DDR DDRB

#define SPI_MISO PB4
#define SPI_MOSI PB3
#define SPI_SCK PB5
#define SPI_SS PB2	

//настройка параметров работы функций
#define BTN_LOCK_TIME		50					/*время обработки дребезга в милисекундах (10-100)*/
#define BTN_LONG_TIME		2000		/*время фиксации длинного нажатия в милисекундах (1000 - 2500)*/
//настройки портов
/*порт чтения кнопок*/
#define BTN_PORT			PORTC
#define BTN_DDR				DDRC
#define BTN_PIN				PINC
/*пины чтения кнопок*/
#define BTN_LINE_UP		(1<<0)
#define BTN_LINE_DN		(1<<1)
#define BTN_LINE_POWER	(1<<2)
#define BTN_LINE_SW		(1<<3)
//глобальные переменные
volatile uint8_t BtnFlags;					//байт флагов нажатия кнопки
#define BTN_SHRT_UP			(1<<0)			/*бит короткого нажатия кнопки up*/
#define BTN_SHRT_DN			(1<<1)			/*бит короткого нажатия кнопки dn*/
#define BTN_SHRT_POWER		(1<<2)			/*бит короткого нажатия кнопки POWER */
#define BTN_SHRT_SW			(1<<3)			/*бит короткого нажатия кнопки SW*/
#define BTN_LONG_UP			(1<<4)			/*бит длинного нажатия кнопки up*/
#define BTN_LONG_DN			(1<<5)			/*бит длинного нажатия кнопки dn*/
#define BTN_LONG_SW			(1<<6)			/*бит короткого нажатия кнопки SW*/
//Функция настройки библиотеки работы с кнопками
void BtnInit (void)
{
	BTN_DDR &= ~(BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER|BTN_LINE_SW);//на ввод
	BTN_PORT |= (BTN_LINE_UP| BTN_LINE_DN| BTN_LINE_POWER|BTN_LINE_SW);//подтяжка вкл
}
//------------------------------------------------------------------------------------------------------
//Функция чтения данных о нажатии кнопок
char BtnGet (void)
{
	cli();
	char temp = BtnFlags;
	BtnFlags = 0;
	sei();
	return temp;
}
//-------------------------------------------------------------------------------------------------------
//короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags
//длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags
void BtnExe (void)
{
	static unsigned char BtnLockBit;				//защелка (защита от дребезга)
	static unsigned char BtnLockCoun;			//счетчик защелки (защита от дребезга)
	static unsigned char BtnLongCoun;			//счетчик длинного нажатия
	static unsigned char BtnLastState;			//последнее состояние кнопок перед отпусканием

	char mask = 0;
	if (! (BTN_PIN & BTN_LINE_UP))		mask = BTN_SHRT_UP;
	if (! (BTN_PIN & BTN_LINE_DN))		mask = BTN_SHRT_DN;
	if (! (BTN_PIN & BTN_LINE_POWER))	mask = BTN_SHRT_POWER;
	if (! (BTN_PIN & BTN_LINE_SW))		mask = BTN_SHRT_SW;

	if (mask){									//опрос состояния кнопки
		if (BtnLockCoun < (BTN_LOCK_TIME/10)){	//клавиша нажата
			BtnLockCoun++;
			return;								//защелка еще не дощитала - возврат
		}
		BtnLastState = mask;
		BtnLockBit =1;							//нажатие зафиксировано
		if (BtnLongCoun >= (BTN_LONG_TIME/10))
		return;								//возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше
		if (++BtnLongCoun >= (BTN_LONG_TIME/10))
		BtnFlags |= (BtnLastState<<4);			//счетчик досчитал до максимума - устанавливаем биты длинного нажатия
	}
	else{										//клавиша отжата
		if (BtnLockCoun){
			BtnLockCoun --;
			return;								//защелка еще не обнулилась - возврат
		}
		if (! BtnLockBit)						//СТАТИЧЕСКИЙ ВОЗВРАТ
		return;
		BtnLockBit =0;							//отжатие зафиксировано
		if (BtnLongCoun < (BTN_LONG_TIME/10))
		BtnFlags |= BtnLastState;			//установка бита короткого нажатия
		BtnLongCoun = 0;					//сброс счетчика длительности нажатия
	}
}
/******************************************************************************************************/
struct UnionBits
{
	unsigned DO0: 1;
	unsigned DO1: 1;
	unsigned DO2: 1;
	unsigned DO3: 1;
	unsigned DO4: 1;
	unsigned DO5: 1;
	unsigned DO6: 1;
	unsigned DO7: 1;
};

union Byte {
	uint8_t ByteRegister;
	struct UnionBits Register;
};

union Byte OneOUT;
union Byte TwoOUT;
union Byte ThreeOUT;
union Byte FourOUT;
union Byte FifthOUT;
union Byte SixOUT;
union Byte SevenOUT;
union Byte EightOUT; 

union Byte OneIN;
union Byte TwoIN;
union Byte ThreeIN;
union Byte FourIN;
union Byte FifthIN;
union Byte SixIN;
union Byte SevenIN;
union Byte EightIN; 

#define AMOUNT_TIMERS 5	//Количество используемых таймеров
typedef struct 
{
	uint8_t FlagTimersON;		//Флаг работы таймера
	uint8_t FlagTimersOFF;
	volatile uint32_t TimeCountingON;	//Переменная фиксирующая время старта
	volatile uint32_t TimeCountingOFF;
}TimerStruct;

typedef struct 
{
	TimerStruct Channel[AMOUNT_TIMERS];
	volatile uint32_t MS;
	volatile uint32_t TimeCurrent;	//Текущие время
}SoftTimers;
SoftTimers TIMER;
/*Функция инициализации таймеров (установка всех значений в 0 )*/
void InitTimers()
{
	TIMER.TimeCurrent=0;
	TIMER.MS=0;
	for(uint8_t i=0;i<AMOUNT_TIMERS;i++)
	{
		TIMER.Channel[i].FlagTimersON=0;
		TIMER.Channel[i].FlagTimersOFF=0;
		TIMER.Channel[i].TimeCountingON=0;
	}
}
//Функция включения сегментов + кодировка.
#define SEG_PORT EightOUT.ByteRegister
#define SEGA 0
#define SEGB 1
#define SEGC 2
#define SEGD 3
#define SEGE 4
#define SEGF 5
#define SEGG 6
#define SEGH 7

#define ANOD1 SevenOUT.Register.DO5
#define ANOD2 SevenOUT.Register.DO6
#define ANOD3 SevenOUT.Register.DO7

static void segchar (unsigned char seg)
{
	switch (seg)
	{
		case 0:
		SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
		case 1:
		SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
		case 2:
		SEG_PORT=(0<<SEGA)|(0<<SEGB)|(1<<SEGC)|(0<<SEGD)|(0<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 3:
		SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 4:
		SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 5:
		SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 6:
		SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 7:
		SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
		case 8:
		SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 9:
		SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 99: //OFF Все сегменты
		SEG_PORT=(1<<SEGA)|(1<<SEGB)|(1<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
	}
}
volatile uint8_t data1=0;
volatile uint8_t data2=0;
volatile uint8_t AnodCount=0;

void WriteSegNumber(uint8_t Seg3,uint8_t NeberChar)
{
	data1=NeberChar%10;
	data2=NeberChar/10;
	AnodCount++;
	switch (AnodCount)
	{
		case 1:	
		segchar(data1);
		ANOD2=1;
		ANOD3=1;
		ANOD1=0;break; 
		case 2:
		segchar(data2);
		ANOD1=1;
		ANOD3=1;
		ANOD2=0;break; 
		case 3:
		segchar(Seg3);
		ANOD1=1;
		ANOD2=1;
		ANOD3=0;
		AnodCount = 0;break;
	}
}
#define MAX_UINT32 4294967295UL
ISR (TIMER0_OVF_vect)
{
	TCNT0=125;		//значение для T0_0VF переполнения 1 раз в MS
	TIMER.MS++;		//Подсчет MS
	if (TIMER.MS == MAX_UINT32)
	{
		TIMER.MS=0;
	}
	BtnExe();
}

/*Функция вернет TRUE через время TimeVar,Иначе возвращает  CurrentFlag */
uint8_t OnAfterTimeMS(uint32_t TimeVar,uint8_t Number,uint8_t CurrentFlag)
{
	cli();
	uint8_t OutFlag=CurrentFlag;			//Переменная отвечает за RETURN f().
	TIMER.TimeCurrent=TIMER.MS;				//Присваиваем текущие значение МС
	//Условия для захвата времени вызова функции, и установки флага работы
	if (TIMER.Channel[Number].FlagTimersON==0)	
	{
		TIMER.Channel[Number].TimeCountingON=TIMER.MS;
		TIMER.Channel[Number].FlagTimersON=1;
	}
	volatile uint32_t TimerToStart = TIMER.TimeCurrent-TIMER.Channel[Number].TimeCountingON;
	//Если (время до старта == TimeVar) и (условия по переполнению MAX_UINT32 выполняеться), 
	//то OutFlag=1 и обнуляем Флаг работы
	if ((TimerToStart >= TimeVar)&&((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)>TimeVar))
	{
		OutFlag=1;
		TIMER.Channel[Number].FlagTimersON=0;
		TIMER.Channel[Number].TimeCountingON=0;
		TimerToStart=0;
	}
	else
	{
		OutFlag=CurrentFlag;
		//Если MAX_UINT32 переполниться быстрей чем досчитает TimeVar то обнулим таймер
		if (((MAX_UINT32-TIMER.Channel[Number].TimeCountingON)<TimeVar))
		{
			TIMER.MS=0;
			TIMER.Channel[Number].TimeCountingON=0;
		}
	}
	sei();
	return OutFlag;
}

uint8_t OFFAfterTimeMS(uint32_t TimeVar,uint8_t Number,uint8_t CurrentFlag)
{
	cli();
	uint8_t OutFlag=CurrentFlag;						//Переменная отвечает за RETURN f().
	TIMER.TimeCurrent=TIMER.MS;				//Присваиваем текущие значение МС
	//Условия для захвата времени вызова функции и установки флага работы
	if (TIMER.Channel[Number].FlagTimersOFF==0)	
	{
		TIMER.Channel[Number].TimeCountingOFF=TIMER.MS;
		TIMER.Channel[Number].FlagTimersOFF=1;
	}
	volatile uint32_t TimerToSTOP = TIMER.TimeCurrent-TIMER.Channel[Number].TimeCountingOFF;
	//Если (время до старта == TimeVar) и (условия по переполнению MAX_UINT32 выполняеться), 
	//то OutFlag=0 и обнуляем Флаг работы
	if ((TimerToSTOP >= TimeVar)&&((MAX_UINT32-TIMER.Channel[Number].TimeCountingOFF)>TimeVar))
	{
		OutFlag=0;
		TIMER.Channel[Number].FlagTimersOFF=0;
		TIMER.Channel[Number].TimeCountingOFF=0;
		TimerToSTOP=0;
	}
	else
	{
		OutFlag=CurrentFlag;
		//Если MAX_UINT32 переполниться быстрей чем досчитает TimeVar то обнулим таймер
		if (((MAX_UINT32-TIMER.Channel[Number].TimeCountingOFF)<TimeVar))
		{
			TIMER.MS=0;
			TIMER.Channel[Number].TimeCountingOFF=0;
		}
	}
	sei();
	return OutFlag;
}
void StartInitIO()
{
	OneOUT.ByteRegister=0x00;
	TwoOUT.ByteRegister=0x00;
	ThreeOUT.ByteRegister=0x00;
	FourOUT.ByteRegister=0x00;
	FifthOUT.ByteRegister=0x00;
	SixOUT.ByteRegister=0x00;
	SevenOUT.ByteRegister=0x00;
	EightOUT.ByteRegister=0x00;
	
	OneIN.ByteRegister=0x00;
	TwoIN.ByteRegister=0x00;
	ThreeIN.ByteRegister=0x00;
	FourIN.ByteRegister=0x00;
	FifthIN.ByteRegister=0x00;
	SixIN.ByteRegister=0x00;
	SevenIN.ByteRegister=0x00;
	EightIN.ByteRegister=0x00;
}

/*инициализация SPI модуля в режиме master*/
void SPI_Init(void)
{
   /*настройка портов ввода-вывода
   все выводы, кроме MISO выходы*/
   SPI_DDR |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO);
   SPI_PORT |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO);
   
   SPCR = (1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(0<<SPR1)|(0<<SPR0);
   SPSR = (0<<SPI2X);
}

uint8_t SPI_UpdataByte(uint8_t data)
{
	uint8_t report;
	SPDR = data;
	while(!(SPSR & (1<<SPIF)));
	report = SPDR;
	return report;
}
void SpiOutRegister()
{
	SPI_PORT &= ~(1<<SPI_SS);
	OneIN.ByteRegister=SPI_UpdataByte(EightOUT.ByteRegister);
	TwoIN.ByteRegister=SPI_UpdataByte(SevenOUT.ByteRegister);
	ThreeIN.ByteRegister=SPI_UpdataByte(SixOUT.ByteRegister);
	FourIN.ByteRegister=SPI_UpdataByte(FifthOUT.ByteRegister);
	FifthIN.ByteRegister=SPI_UpdataByte(FourOUT.ByteRegister);
	SixIN.ByteRegister=SPI_UpdataByte(ThreeOUT.ByteRegister);
	SevenIN.ByteRegister=SPI_UpdataByte(TwoOUT.ByteRegister);
	EightIN.ByteRegister=SPI_UpdataByte(OneOUT.ByteRegister);
	SPI_PORT |= (1<<SPI_SS);
}
void  TransmitStatusGerkonToLed()
{
	OneOUT.ByteRegister=FourIN.ByteRegister;
	TwoOUT.ByteRegister=FifthIN.ByteRegister;
	ThreeOUT.ByteRegister=SixIN.ByteRegister;
	FourOUT.ByteRegister=SevenIN.ByteRegister;
}
void  TransmitStatusTumblerSwToLed()
{
	FifthOUT.ByteRegister=OneIN.ByteRegister;
	SixOUT.ByteRegister=TwoIN.ByteRegister;
	SevenOUT.Register.DO0=ThreeIN.Register.DO0;
	SevenOUT.Register.DO1=ThreeIN.Register.DO1;
	SevenOUT.Register.DO2=ThreeIN.Register.DO2;
	SevenOUT.Register.DO3=ThreeIN.Register.DO3;
	SevenOUT.Register.DO4=ThreeIN.Register.DO4;
}

volatile uint8_t flagBtnLnUp=0;
void BtnUpdate(void)
{
	char BtnMask = BtnGet ();
	if (BtnMask == BTN_SHRT_POWER)
	{
	}
	if ((BtnMask == BTN_SHRT_SW))
	{
	}
	//одиночное нажатие +
	if (BtnMask == BTN_SHRT_UP)
	{
		TEST++;
	}
	//одиночное нажатие -
	if ((BtnMask == BTN_SHRT_DN))
	{
		TEST--;
	}
	//Удержание +
	if ((BtnMask == BTN_LONG_UP))
	{
		flagBtnLnUp=1;
	}
	//Удержание -
	if ((BtnMask == BTN_LONG_DN))
	{
		TEST--;
	}
}

void Algoritm()
{
	
}

void DebugAlgoritm()
{
	TransmitStatusTumblerSwToLed();
	TransmitStatusGerkonToLed();
}

uint8_t Step=0;
int main(void)
{
	SPI_Init();
	StartInitIO();
	InitTimers();
	BtnInit();
	DDRD=0xFF;
	ANOD1=1;ANOD2=1;ANOD3=1;segchar(99);//Офф 7сег индикация.
	TCCR0=(1<<CS01)|(1<<CS00); //Настраиваем пред делитель 64
	TIMSK=(1<<TOIE0); // Запускаем таймер
	TCNT0=131;
	sei();
	while(1)
	{
		Step++;
		switch (Step)
		{
			case 1:
			SpiOutRegister();break;
			case 2:
			WriteSegNumber(3,21);break;
			case 3:
			DebugAlgoritm();break;
			case 4:
			BtnUpdate();
			Step=0;break;
		}
	}
	return 0;
}

Код Функции динамической индикации:

Код: Выделить всё

//Функция включения сегментов + кодировка.
#define SEG_PORT EightOUT.ByteRegister
#define SEGA 0
#define SEGB 1
#define SEGC 2
#define SEGD 3
#define SEGE 4
#define SEGF 5
#define SEGG 6
#define SEGH 7

#define ANOD1 SevenOUT.Register.DO5
#define ANOD2 SevenOUT.Register.DO6
#define ANOD3 SevenOUT.Register.DO7

static void segchar (unsigned char seg)
{
	switch (seg)
	{
		case 0:
		SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
		case 1:
		SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
		case 2:
		SEG_PORT=(0<<SEGA)|(0<<SEGB)|(1<<SEGC)|(0<<SEGD)|(0<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 3:
		SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 4:
		SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 5:
		SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 6:
		SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 7:
		SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
		case 8:
		SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 9:
		SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
		case 99: //OFF Все сегменты
		SEG_PORT=(1<<SEGA)|(1<<SEGB)|(1<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
	}
}
volatile uint8_t data1=0;
volatile uint8_t data2=0;
volatile uint8_t AnodCount=0;

void WriteSegNumber(uint8_t Seg3,uint8_t NeberChar)
{
	data1=NeberChar%10;
	data2=NeberChar/10;
	AnodCount++;
	switch (AnodCount)
	{
		case 1:	
		segchar(data1);
		ANOD2=1;
		ANOD3=1;
		ANOD1=0;break; 
		case 2:
		segchar(data2);
		ANOD1=1;
		ANOD3=1;
		ANOD2=0;break; 
		case 3:
		segchar(Seg3);
		ANOD1=1;
		ANOD2=1;
		ANOD3=0;
		AnodCount = 0;break;
	}
}

Re: Динамическая индикация на 74HC597

Добавлено: Ср ноя 15, 2017 07:22:10
Dimon456
У вас

Код: Выделить всё

SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
К примеру SEGG- это 1(первый) бит, а в схеме R8ANOD G подключен на 6 бит ---- это правильно?

Re: Динамическая индикация на 74HC597

Добавлено: Ср ноя 15, 2017 07:48:35
7seg
Это пологаю что это правильно т.к SEGG находиться в структуре :: EightOUT.ByteRegister

Код: Выделить всё

struct UnionBits
{
   unsigned DO0: 1;
   unsigned DO1: 1;
   unsigned DO2: 1;
   unsigned DO3: 1;
   unsigned DO4: 1;
   unsigned DO5: 1;
   unsigned DO6: 1;
   unsigned DO7: 1;
};

union Byte {
   uint8_t ByteRegister;
   struct UnionBits Register;
};
union Byte EightOUT;

и при передачи (1<<SEGG), т.е мы установим 1 в EightOUT.Register.DO6 , а это битовое поле как раз и отвечает за Q6 в регистре "R8ANOD".

Добавлено after 6 minutes 34 seconds:
Такая если конечно можно выразиться "инверсия" происходит из-за SPI и принципа работы сдвиговых регистров.

Код: Выделить всё

uint8_t SPI_UpdataByte(uint8_t data)
{
   uint8_t report;
   SPDR = data;
   while(!(SPSR & (1<<SPIF)));
   report = SPDR;
   return report;
}
void SpiOutRegister()
{
   SPI_PORT &= ~(1<<SPI_SS);
   OneIN.ByteRegister=SPI_UpdataByte(EightOUT.ByteRegister);
   TwoIN.ByteRegister=SPI_UpdataByte(SevenOUT.ByteRegister);
   ThreeIN.ByteRegister=SPI_UpdataByte(SixOUT.ByteRegister);
   FourIN.ByteRegister=SPI_UpdataByte(FifthOUT.ByteRegister);
   FifthIN.ByteRegister=SPI_UpdataByte(FourOUT.ByteRegister);
   SixIN.ByteRegister=SPI_UpdataByte(ThreeOUT.ByteRegister);
   SevenIN.ByteRegister=SPI_UpdataByte(TwoOUT.ByteRegister);
   EightIN.ByteRegister=SPI_UpdataByte(OneOUT.ByteRegister);
   SPI_PORT |= (1<<SPI_SS);
}

Re: Динамическая индикация на 74HC597

Добавлено: Ср ноя 15, 2017 15:57:52
Dimon456
Все таки я ее заставил работать, видос

Re: Динамическая индикация на 74HC597

Добавлено: Чт ноя 16, 2017 04:24:36
7seg
Dimon456, Поздравляю ) а исходником не поделитесь ?)

Добавлено after 35 minutes 34 seconds:
Видос как она ̶Р̶а̶б̶о̶т̶а̶е̶т̶ не работает у меня (

Re: Динамическая индикация на 74HC597

Добавлено: Чт ноя 16, 2017 15:55:13
Dimon456
Исходник я не менял, он ваш полностью и всецело.

Это Протеус косячит, в реальном железе будет работать.
У китайцев же эти модули работают
СпойлерИзображение
Но и Протеус можно заставить корректно отображать, так сказать для отладки, надо просто

Re: Динамическая индикация на 74HC597

Добавлено: Пт ноя 17, 2017 02:46:43
7seg
я тогда предполагаю что это настройки пртеуса. System->Set display options и System->Animation Options.

Re: Динамическая индикация на 74HC597

Добавлено: Пт ноя 17, 2017 08:58:49
Dimon456
Я же написал, странно, ну да ладно.

Нет, неверно, но если ваш компутер переваривает 100 кадр/сек, можете поставить. Я туда не лазил.

Просто отсоедините вывод OE микрух R3R и R8ANOD от общей схемы, что бы они в воздухе оказались, соедините их между собой, подсоедините это соединение OE через инвертор к точке соединения выводов ST_CP микрух R3R и R8ANOD.

Если не понятно вот схема
СпойлерИзображение
Еще раз говорю, исходный код тот же, ни чего не надо там менять, это только для отладки в протеусе, в реальной схеме будет работать и без этого.
Это только для вашего кода, вы неверно формируете импульс ST_CP для 74HC595, хотя этот импульс может быть верен для 74HC165 (не разбирался с ней, не знаю). Это только для протеуса. Инвертор формирует правильный импульс для вывода OE. Не зацикливайтесь на этом.
СпойлерИзображение

Re: Динамическая индикация на 74HC597

Добавлено: Вс ноя 19, 2017 13:42:04
Starichok51
7seg писал(а):#define SEG_PORT EightOUT.ByteRegister
#define SEGA 0
#define SEGB 1
#define SEGC 2
#define SEGD 3
#define SEGE 4
#define SEGF 5
#define SEGG 6
#define SEGH 7

#define ANOD1 SevenOUT.Register.DO5
#define ANOD2 SevenOUT.Register.DO6
#define ANOD3 SevenOUT.Register.DO7

static void segchar (unsigned char seg)
{
switch (seg)
{
case 0:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
case 1:
SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
case 2:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(1<<SEGC)|(0<<SEGD)|(0<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 3:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 4:
SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 5:
SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 6:
SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 7:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
case 8:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 9:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 99: //OFF Все сегменты
SEG_PORT=(1<<SEGA)|(1<<SEGB)|(1<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
}
}
все это до фига избыточно (как и многое другое в полном коде).
достаточно определить байты цифр - по одному байту для каждой цифры.
вот, как это сделано у меня:

; 0 - горит, 1 - потушен
; сегменты: D.CGAFBE
.equ _0 = 0b01010000
.equ _1 = 0b11011101
.equ _2 = 0b01100100
.equ _3 = 0b01000101
.equ _4 = 0b11001001
.equ _5 = 0b01000011
.equ _6 = 0b01000010
.equ _7 = 0b11010101
.equ _8 = 0b01000000
.equ _9 = 0b01000001
.equ _x = 0b11111111 ; пустое место, пробел
.equ _m = 0b11101111 ; минус

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

далее все просто: соответственно цифре ее код (байт) отправляем прямо в порт. либо другой нужный символ.
и не нужны твои огромные навороты с объявлениями большой кучи констант и созданием комбинаций из этих констант...

Re: Динамическая индикация на 74HC597

Добавлено: Вс ноя 19, 2017 18:24:58
Demiurg
Писанины много, это так. Но тут полностью работает пословица: долго запрягаем, зато быстро едем. Последующие проекты собираются гораздо быстрее. Тебе остается переопределить пины и все. Немного посложнее с микросхемами ввода-вывода. Но все равно, при шаблоне проект гораздо быстрее собрать, чем с нуля все писать.
Динамическая индикация. Расширение ввода-вывода. 74HC595. Период вывода 1 мс. Функция работает в основном цикле. Ну про свой подход в программировании я неоднократно писал.

"seven_segm_led_ind.h"
Спойлер

Код: Выделить всё

//==================
#ifndef SEVEN_SEGM_LED_IND_H

#define SEVEN_SEGM_LED_IND_H

#include "seven_segm_led_ind.h"
//==================

//==================
#include "main_def_func.h"
//==================

//==================
//#define __COMMON_METHOD_ONE__
#define __COMMON_METHOD_ZERO__

//#define __SEGMENT_METHOD_ONE__
#define __SEGMENT_METHOD_ZERO__
//==================

//==================
#define IND_1              b00000010 // 1<<1
#define IND_2              b00000100 // 1<<2
#define IND_3              b00001000 // 1<<3
#define IND_4              b00000001 // 1<<0

#ifdef __COMMON_METHOD_ONE__
#define IND_1_MASK         IND_1
#define IND_2_MASK         IND_2
#define IND_3_MASK         IND_3
#define IND_4_MASK         IND_4
#endif

#ifdef __COMMON_METHOD_ZERO__
#define IND_1_MASK         (0xFF ^ (IND_1))
#define IND_2_MASK         (0xFF ^ (IND_2))
#define IND_3_MASK         (0xFF ^ (IND_3))
#define IND_4_MASK         (0xFF ^ (IND_4))
#endif
//------------------------------------------------------------------------
#define SEG_A              b00000010 // 1<<1
#define SEG_B              b00001000 // 1<<3 //     A
#define SEG_C              b10000000 // 1<<7 //   F   B
#define SEG_D              b00100000 // 1<<5 //     G
#define SEG_E              b00010000 // 1<<4 //   E   C
#define SEG_F              b00000100 // 1<<2 //     D   H
#define SEG_G              b00000001 // 1<<0
#define SEG_H              b01000000 // 1<<6
//------------------------------------------------------------------------
typedef struct tab_char_7_segm_cod_t
{
   u08 Char;
   u08 seven_segm_cod;
} tab_char_7_segm_cod_t;

extern struct tab_char_7_segm_cod_t __flash tab_char_7_segm_cod [];
//==================

//==================
#define MAX_LED_INDS       4
//==================

//==================
extern u08 dsp_buf [];

void clr_dsp_buf (void);
//==================

//==================
typedef struct index_inds
{
   u08 i;
   u08 ind;
} index_inds;
//==================

//==================
u08 recod_char_7_segm_cod (u08 data);

void set_proc_7_segm_ind_on (void);
void set_proc_7_segm_ind_off (void);
void proc_7_segm_ind (void);
//==================

//==================
#endif
//==================
"seven_segm_led_ind.с"
Спойлер

Код: Выделить всё

//==================
#include "seven_segm_led_ind.h"
//==================

//==================
struct index_inds __flash tab_index_inds [] =
{
   {1,      IND_2_MASK},
   {2,      IND_3_MASK},
   {3,      IND_4_MASK},
   {0,      IND_1_MASK},
};

struct tab_char_7_segm_cod_t __flash tab_char_7_segm_cod [] =
{
#ifdef __SEGMENT_METHOD_ONE__
   {'0',   (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F)},                  // 0
   {'1',   (SEG_B | SEG_C)},                                                  // 1
   {'2',   (SEG_A | SEG_B | SEG_D | SEG_E | SEG_G)},                          // 2
   {'3',   (SEG_A | SEG_B | SEG_C | SEG_D | SEG_G)},                          // 3
   {'4',   (SEG_B | SEG_C | SEG_F | SEG_G)},                                  // 4
   {'5',   (SEG_A | SEG_C | SEG_D | SEG_F | SEG_G)},                          // 5
   {'6',   (SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)},                  // 6
   {'7',   (SEG_A | SEG_B | SEG_C)},                                          // 7
   {'8',   (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)},          // 8
   {'9',   (SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G)},                  // 9
   {'A',   (SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G)},                  // 10
   {'B',   (SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)},                          // 11
   {'C',   (SEG_A | SEG_D | SEG_E | SEG_F)},                                  // 12
   {'D',   (SEG_B | SEG_C | SEG_D | SEG_E | SEG_G)},                          // 13
   {'E',   (SEG_A | SEG_D | SEG_E | SEG_F | SEG_G)},                          // 14
   {'F',   (SEG_A | SEG_E | SEG_F | SEG_G)},                                  // 15
   {'G',   (SEG_A | SEG_C | SEG_D | SEG_E | SEG_F)},                          // 16
   {'H',   (SEG_B | SEG_C | SEG_E | SEG_F | SEG_G)},                          // 17
   {'L',   (SEG_D | SEG_E | SEG_F)},                                          // 18
   {'N',   (SEG_C | SEG_E | SEG_G)},                                          // 19
   {'O',   (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F)},                  // 20
   {'P',   (SEG_A | SEG_B | SEG_E | SEG_F | SEG_G)},                          // 21
   {'П',   (SEG_A | SEG_B | SEG_C | SEG_E | SEG_F)},                          // 22
   {'-',   (SEG_G)},                                                          // 23
   {' ',   0xFF},                                                             // 24
#endif

#ifdef __SEGMENT_METHOD_ZERO__
   {'0',   (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F))},         // 0
   {'1',   (0xFF ^ (SEG_B | SEG_C))},                                         // 1
   {'2',   (0xFF ^ (SEG_A | SEG_B | SEG_D | SEG_E | SEG_G))},                 // 2
   {'3',   (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_D | SEG_G))},                 // 3
   {'4',   (0xFF ^ (SEG_B | SEG_C | SEG_F | SEG_G))},                         // 4
   {'5',   (0xFF ^ (SEG_A | SEG_C | SEG_D | SEG_F | SEG_G))},                 // 5
   {'6',   (0xFF ^ (SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G))},         // 6
   {'7',   (0xFF ^ (SEG_A | SEG_B | SEG_C))},                                 // 7
   {'8',   (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G))}, // 8
   {'9',   (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G))},         // 9
   {'A',   (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G))},         // 10
   {'B',   (0xFF ^ (SEG_C | SEG_D | SEG_E | SEG_F | SEG_G))},                 // 11
   {'C',   (0xFF ^ (SEG_A | SEG_D | SEG_E | SEG_F))},                         // 12
   {'D',   (0xFF ^ (SEG_B | SEG_C | SEG_D | SEG_E | SEG_G))},                 // 13
   {'E',   (0xFF ^ (SEG_A | SEG_D | SEG_E | SEG_F | SEG_G))},                 // 14
   {'F',   (0xFF ^ (SEG_A | SEG_E | SEG_F | SEG_G))},                         // 15
   {'G',   (0xFF ^ (SEG_A | SEG_C | SEG_D | SEG_E | SEG_F))},                 // 16
   {'H',   (0xFF ^ (SEG_B | SEG_C | SEG_E | SEG_F | SEG_G))},                 // 17
   {'L',   (0xFF ^ (SEG_D | SEG_E | SEG_F))},                                 // 18
   {'N',   (0xFF ^ (SEG_C | SEG_E | SEG_G))},                                 // 19
   {'O',   (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F))},         // 20
   {'P',   (0xFF ^ (SEG_A | SEG_B | SEG_E | SEG_F | SEG_G))},                 // 21
   {'П',   (0xFF ^ (SEG_A | SEG_B | SEG_C | SEG_E | SEG_F))},                 // 22
   {'-',   (0xFF ^ (SEG_G))},                                                 // 23
   {' ',   0xFF},                                                             // 24
#endif

   {0xFF,   0xFF},
};
//==================

//==================
u08 dsp_buf [MAX_LED_INDS];
//------------------------------------------------------------------------
// Очистка буфера дисплея.

u08 dsp_buf [MAX_LED_INDS];

void clr_dsp_buf (void)
{
   for (u08 i = 0; i < MAX_LED_INDS; i++)
      dsp_buf [i] = ' ';
}
//==================

//==================
u08 recod_char_7_segm_cod (u08 data)
{
   struct tab_char_7_segm_cod_t __flash *ptr = tab_char_7_segm_cod;

   for (; ptr -> Char != 0xFF; ptr++)
   {
      if (ptr -> Char == data)
         return ptr -> seven_segm_cod;
   }

   return false;
}
//==================

//==================
static u08 _proc_7_segm_ind;

void set_proc_7_segm_ind_on (void)
{
   _proc_7_segm_ind = 1;
}

void set_proc_7_segm_ind_off (void)
{
  _oe_disable ();

   _proc_7_segm_ind = 0;
}

void proc_7_segm_ind (void)
{
   static soft_timer ST_PROC_7_SEGM_IND;

   static u08 cnt_7_segm_ind;

   u08 a;

   u08 inds;
   u08 segments;

   switch (_proc_7_segm_ind)
   {
      case 0:
         break;

      case 1:
         spi_init ();

         cnt_7_segm_ind = 0;

         set_soft_timer (ST_PROC_7_SEGM_IND, 1, 1);
         _proc_7_segm_ind = 2;
         break;

      case 2:
         if (handle_soft_timer (ST_PROC_7_SEGM_IND))
         {
            u08 cnt = cnt_7_segm_ind;

            cnt_7_segm_ind = tab_index_inds [cnt].i;
            inds = tab_index_inds [cnt].ind;

            segments = recod_char_7_segm_cod (dsp_buf [cnt_7_segm_ind]);

            spi_transf_buf [0] = inds;

            a = segments;

            if ((get_dp_flag () == true) && (cnt_7_segm_ind == 2))
            {
               #ifdef __SEGMENT_METHOD_ONE__
               a |= SEG_H;
               #endif

               #ifdef __SEGMENT_METHOD_ZERO__
               a &= (0xFF ^ SEG_H);
               #endif
            }

            spi_transf_buf [1] = a;

            strob_latch_in ();

            for (u08 i = 0; i < SPI_BYTES; i++)
            {
               spi_transf (i);
               spi_receive_buf [i] = SPDR;
            }

            _oe_disable ();

            strob_latch_out ();

            _oe_enable ();
         }
         break;

      default:
         break;
   }
}
//==================

Re: Динамическая индикация на 74HC597

Добавлено: Вс ноя 19, 2017 22:34:29
asus2015
Исправьте в название регистр 595й

Re: Динамическая индикация на 74HC597

Добавлено: Пн ноя 20, 2017 03:12:42
7seg
Уважаемый модератор исправьте пожалуйста ошибочку в название темы, которая была допущена мною ( .
На Динамическая индикация на 74HC595

Re: Динамическая индикация на 74HC597

Добавлено: Пн ноя 20, 2017 03:14:19
Demiurg
Это можно и самому сделать. Правка и меняете заголовок.

Re: Динамическая индикация на 74HC595

Добавлено: Пн ноя 20, 2017 03:29:43
7seg
Starichok51, в первых прошивках делал по принципу который вы описали ) но как оказалось при смени камня или печатной латы даже того же индикатора ,следовало вносить очень много правок (. Поэтому было решено написать более универсальную функцию, и теперь всё изменения кода сводиться к правке дефайнов.

Добавлено after 2 minutes 15 seconds:
Re: Динамическая индикация на 74HC597
Demiurg, к сожалению править можно только свежие посты(

Re: Динамическая индикация на 74HC595

Добавлено: Пн ноя 20, 2017 06:39:21
Starichok51
я исправил название.

если нужна портация под разные устройства, тогда ты прав, и я беру свои слова обратно.

Re: Динамическая индикация на 74HC595

Добавлено: Пн ноя 20, 2017 06:49:16
7seg
Не хочу создавать новую тему решил спросить тут, может кто посоветовать для прочтения книжечку/статейки про КА(конечные автоматы)?, а если в ней еще будут примеры то было бы совсем замечательно )

Добавлено after 36 seconds:
И спасибо за правку названия темы Starichok51.

Re: Динамическая индикация на 74HC595

Добавлено: Пн ноя 20, 2017 07:24:57
Demiurg
Почему-то пропали статьи. Тут про них написано. Там же ссылка на архив статей Татарчевского. Лично я с этих статей многое почерпнул.
Ищите также Шалыто. Ну и "автоматное программирование", "конечные автоматы".

Re: Динамическая индикация на 74HC595

Добавлено: Пн ноя 20, 2017 08:05:57
7seg
Demiurg, Спасибо за Статью и автора книги, попробую проникнуться парадигмой автома́тного программи́рования )

Re: Динамическая индикация на 74HC595

Добавлено: Пт ноя 24, 2017 09:41:35
7seg
Дабы не создавать новую тему , есть у кого на примете (твердотельные реле или гальванически развязанные ключи ) ? DIP4
На подобии KAQY214 или PVA3054NPBF.
Просто (PC817+Транзистор) слишком много места занимают (.
Характеристики нагрузки: 12..24V 100mA. Управление сдвиговые регистры или сам МК.

Re: Динамическая индикация на 74HC595

Добавлено: Пт ноя 24, 2017 09:53:05
Demiurg
PRAB37S. Отечественные. Протон-Орел. Сам использую. Доволен. У мну есть сколько-то. Запас. Сколько не помню, надо смотреть.