Files
Balsam_167/Source/Internal/kanal.c

208 lines
4.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file kanal.c
* @brief Последовательный вывод числовых данных на канальный индикатор.
*
* Управляет линиями DCLK/DOUT, формирует импульс сброса и передаёт разряды
* индикатора с учётом адреса, десятичной точки и множителя тактовой частоты.
* Задержки и таблица сегментов привязаны к внешней схеме; изменение GPIO или
* CLKMULT требует повторной проверки временной диаграммы.
*/
#include "DSP2833x_Device.h" // DSP281x Headerfile Include File
#include "DSP2833x_SWPrioritizedIsrLevels.h"
#include "filter_bat2.h"
#include "measure.h"
#include "RS485.h"
#include "message.h"
#include "kanal.h"
#include "pulto.h"
#include "package.h"
#include "tools.h"
#include "peripher.h"
int digits[16] = {63,6,91,79,102,109,125,7,127,111,64,0,0,0,121,0};
int readr[5] = {0x08,0x0C,0x10,0x00,0x04};
/** @brief Устанавливает тактовую линию канального последовательного интерфейса. */
void DCLK(int x)
{
if(x) GpioDataRegs.GPASET.bit.GPIO6=1;
else GpioDataRegs.GPACLEAR.bit.GPIO6=1;
}
/** @brief Устанавливает линию данных канального последовательного интерфейса. */
void DOUT(int x)
{
if(x) GpioDataRegs.GPASET.bit.GPIO8=1;
else GpioDataRegs.GPACLEAR.bit.GPIO8=1;
}
#if CLKMULT==1
#define POWS0 0L
#define POWS1 10L
#endif
#if CLKMULT==2
#define POWS0 0L
#define POWS1 30L
#endif
#if CLKMULT==3
#define POWS0 1L
#define POWS1 50L
#endif
#if CLKMULT==4
#define POWS0 2L
#define POWS1 60L
#endif
#if CLKMULT==5
#define POWS0 4L
#define POWS1 80L
#endif
/**
* @brief Формирует последовательность сброса внешних регистров индикатора.
* @note Число холостых тактов является частью аппаратного протокола.
*/
void RESET()
{
DCLK(0);
#if POWS1>0
DSP28x_usDelay(POWS1);
#endif
DOUT(1);
#if POWS1>0
DSP28x_usDelay(POWS1);
#endif
DOUT(0);
#if POWS1>0
DSP28x_usDelay(POWS1);
#endif
}
/** @brief Выдаёт один бит данных и сопровождающий его импульс DCLK. */
void SENDBIT(int x)
{
DOUT(x); DCLK(1);
#if POWS0>0
DSP28x_usDelay(POWS0);
#endif
DOUT(0);
DSP28x_usDelay(POWS0+1);
DCLK(0);
#if POWS1>0
DSP28x_usDelay(POWS1);
#endif
}
/**
* @brief Кодирует адрес и число и передаёт их семисегментному индикатору.
* @param adr Адрес физического канала.
* @param dat Значение для отображения.
* @param dot Позиция десятичной точки.
* @details Таблица digits преобразует цифры в сегменты; знак и ведущие позиции
* обрабатываются до побитовой отправки каждого разряда.
*/
void kanal_Send(int adr, long dat, int dot)
{
long Word,data,aliq_part,dg[4];
int i,j,bit,byt,addr,sgn=0,punkt=0,aliq_len=0,full_len, isdot=0;
if(adr>1) // Лампочки
{
Word =dat;
}
else
{
if(dat<0) sgn=1;
data = labs(dat);
if(dot>=0 && dot<4) isdot = 1;
else dot=0;
aliq_part = data;
for(i=0;i<dot;i++) aliq_part/=10;
dat = aliq_part;
while(dat>0)
{
aliq_len++; dat/=10;
}
dat = data;
full_len = aliq_len+sgn;
if(full_len==0) full_len=1;
full_len += dot;
for(i=0; i<(full_len-4);i++)
{
dot--; dat/=10;
}
if(dot<0) dot=0;
punkt = 1<<dot;
if(punkt==1) punkt=0;
dg[3] = (dat)/1000;
dg[2] = (dat%1000)/100;
dg[1] = (dat%100)/10;
dg[0] = (dat%10);
if(dg[0]+dg[1]+dg[2]+dg[3]==0)
{
punkt=0; dot=0; sgn=0;
}
if(isdot)
for(i=3;i>0;i--)
{
if((dg[i]==0)&&(i!=dot))
dg[i]=0xF; // Это значит пусто
else break;
}
if(sgn)
for(i=1;i<4;i++)
{
if( (dg[i]==0xF)||(i==3))
{
dg[i]=0xA; // Это значит минус
break;
} }
for(i=0;i<4;i++)
{
dg[i] = digits[dg[i]];
if((punkt>>i)&1) dg[i]+= 128;
}
Word = ((dg[0] ) & 0x000000FF) | ((dg[1]<<8 ) & 0x0000FF00) |
((dg[2]<<16) & 0x00FF0000) | ((dg[3]<<24) & 0xFF000000);
}
addr = readr[adr];
for (i=0;i<4;i++)
{
if(addr>0x10) break;
for (j=0;j<8;j++)
{
bit = Word & 1; Word >>= 1;
SENDBIT(bit);
}
byt = addr;
for (j=0;j<6;j++)
{
bit = byt & 1; byt >>= 1;
SENDBIT(bit);
}
addr++;
RESET();
}
}