Динамическая индикация на 74HC595
Добавлено: Ср ноя 15, 2017 03:52:41
Запускаю симуляцию в протеусе динамическая индикация отображается "кракозябрами"(раньше дин.индикация всегда отображалась в протеусе корректно).
Вот и закралась мысль ко мне может я чего то не знаю ?(
Может кто подсказать где кроется ошибка?
Схема:
Фулл код
Код Функции динамической индикации:
Вот и закралась мысль ко мне может я чего то не знаю ?(
Может кто подсказать где кроется ошибка?
Схема:
Спойлер

Спойлер
Код: Выделить всё
#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;
}
}


