Turbo51
Модули АЦП
ADS1100
unit ads1100T;
{$O-}
{$xdata}
{$idata}
//================================================
//БЛОК РАБОТЫ С АЦП ADS1100
interface
var
PSA1100:real; //ХРАНИТЕЛЬ КОДА PSA АЦП
b1100:integer; //СЧИТАННОЕ ЗНАЧЕНИЕ
pb1100:integer;
FORMAT1100:byte; //ХРАНИТЕЛЬ ФОРМАТА ДАННЫХ: 12,14,15 ИЛИ 16
PGA1100:byte; //ХРАНИТЕЛЬ УСИЛЕНИЯ АЦП: 1,2,4,8
ref1100:word; //опорное напряжение ацп
ADR1100:byte; //адрес ацп в серии (0-7)
reg1100:byte; //буфер регистра для записи в ацп параметров его работы
sc1100:boolean; //флаг одиночного преобразования Single Conversion
b1100r:real;
OffsetError:integer; //аддитивная ошибка (ошибка смещения)
NonLinear:real;
Code1100:integer;
//sda:boolean absolute $0a0;
//scl:boolean absolute $0a1;
procedure getadsc;
procedure getadr1100;
procedure Wr1100;
procedure Rd1100;
procedure In1100;
procedure In1100M;
procedure In1100MR;
implementation
uses declare,ports,i2c;
const adr1100g=%10010000;
//===============================================
procedure getadsc;
//ПОДПРОГРАММА ВЫЧИСЛЕНИЯ ПОПРАВОЧНОГO КОЭФФИЦИЕНТА
//ДЛЯ АЦП ADS1100 ПРИ ЗАДАННОМ ФОРМАТЕ И ЗАДАННОМ
//КОЭФФИЦИЕНТЕ УСИЛЕНИЯ, КОТОРЫЕ ЗАДАЮТСЯ В КОН-
//СТАНТАХ FORMAT1100 И PGA1100 СООТВЕТСТВЕННО.
//В РЕЗУЛЬТАТЕ СОДЕРЖИМОЕ ПЕРЕМЕННОЙ PSA1100
//ЯВЛЯЕТСЯ ДЕЛИТЕЛЕМ В ФОРМУЛЕ РАСЧЕТА НАПРЯЖЕНИЯ,
//ЧИСЛИТЕЛЕМ КОТОРОЙ ЯВЛЯЕТСЯ СЧИТАННЫЙ АЦП КОД.
//КРОМЕ ТОГО, ПЕРЕМЕННАЯ REG1100 СОДЕРЖИТ КОНФИГУРАЦИОННЫЙ
//КОД, ЗАПИСЫВАЕМЫЙ В БАЙТ КОНФИГУРАЦИИ АЦП.
begin
reg1100:=$80;
if (format1100=13) or (format1100<12) then format1100:=12;
if format1100>16 then format1100:=16;
case format1100 of //установка DR0 и DR1 в конфигурационном регистре
16: begin valr:=32768;reg1100:=reg1100 or %00001100;end;//16, 32, 64, 128
15: begin valr:=16384;reg1100:=reg1100 or %00001000;end;//8, 16, 32, 64
14: begin valr:=8192;reg1100:=reg1100 or %00000100;end;//4, 8, 16, 32
12: begin valr:=2048;reg1100:=reg1100 or %00000000;end;//1, 2, 4, 8
end;
valr:=valr*pga1100;
psa1100:={round}(valr/ref1100); //вычисление пересчетного коэффициента,
//на значение которого будет делиться код,
//если нужно определить значение входного
//напряжения в мВ.
if sc1100 then reg1100:=reg1100 or %00010000; //установка режима работы АЦП -
//единичное или непрерывное преобразование.
//b:=pga1100;
b:=0;
case pga1100 of
1: b:=0;
2: b:=1;
4: b:=2;
8: b:=3;
end;
//dec(b);
reg1100:=reg1100 or b; //установка PGA0 и PGA1 в конфигурационном регистре
end;
{
7 6 5 4 3 2 1 0
st/drdy 0 0 SC dr1 dr0 pga1 pga0
В режиме единичного преобразования установка бита st/drdy запускает процесс
преобразования. Затем производится непрерывный опрос указанного бита программой
польхователя. Как только он становится равным 0, преобразование завершено,
и данные размещены в выходном регистре. Теперь их можно считать.
В режиме непрерывного преобразования бит st/drdy управляется АЦП. Когда он сброшен,
данные готовы к чтению. После считывания выходного регистра АЦП устанавливает st/drdy
в 1 и держит его на этом уровне до тех пор, пока не произведет следующее преобразование,
после чего опять установит st/drdy в 0.
}
{Более ранняя заметка.
Если АЦП находится в режиме единичного преобразования,
установка ST/DRDY в 1 запускает процесс преобразования.
После окончания данного процесса АЦП устанавливает ST/DRDY
в 0, что означает возможность считывания данных.
В режиме непрерывного преобразования установка ST/DRDY
пользователем в 1 игнорируется АЦП.
По-видимому, ST/DRDY автоматически устанавливается в
1 после чтения данных или чтения регистра состояния.}
//===============================================
//Процедура исходного определения адреса ацп.
//Производится последовательное обращение к АЦП
//с индивидуальным номером от 0 до 7. Как только
//АЦП ответит, происходит выход из подпрограммы
//с назначенным adr1100. Если в указанном диапазоне
//адресов ответ от АЦП не получен, возникает
//ошибка с кодом 17 - "Адрес АЦП не определен".
procedure getadr1100;
begin
//getadsc;
i2cinit;
for adr1100:=0 to 8 do
begin
asm
mov a,adr1100
clr c
rlc a
orl a,#adr1100g
lcall i2cadr
lcall i2cstop
end;
if not I2CError then break;
end;
if adr1100=8 then err:=17 else err:=0;
end;
//===============================================
//процедура записи конфигурационного регистра в ацп
procedure Wr1100;
begin
i2cstart;
asm //формирование старт-байта для записи
mov a,adr1100
clr c
rlc a
orl a,#adr1100g
clr acc.0
end;
i2cwb;
i2cans;
acc:=reg1100;
i2cwb;
i2cans;
i2cstop;
end;
//===============================================
//процедура чтения данных из ацп
procedure Rd1100;
begin
i2cstart;
asm //формирование старт-байта для чтения
mov a,adr1100
clr c
rlc a
orl a,#adr1100g
setb acc.0
end;
i2cwb;
i2cans;
i2crb;
b1100:=acc;
b1100:=b1100 shl 8;
i2cansm;
i2crb;
b1100:=b1100+acc;
i2cansm;
i2crb;
i2cansm;
i2cstop;
cy:=acc.7;
//if not Polarline1100 then b1100:=-b1100;
end;
//===============================================
//процедура чтения данных из ацп с контролем готовности
procedure Rd1100s;
begin
//repeat
while 1<>0 do
begin
rd1100;
if not cy then exit; //ждем готовности данных
end;
//until not cy;
end;
//===============================================
//процедура полного цикла работы ацп с выдачей кода
procedure In1100;
begin
wr1100; //запись конфигурационного регистра,
//в режиме одиночного преобразования - запуск.
rd1100s; //проверка готовности данных и их считывание
b1100:=b1100+OffsetError;
end;
//===============================================
//процедура полного цикла работы ацп с выдачей
//результата в милливольтах
procedure In1100M;
begin
wr1100; //запись конфигурационного регистра,
//в режиме одиночного преобразования - запуск.
rd1100s; //проверка готовности данных и их считывание
b1100:=b1100+OffsetError;
b1100:=round(b1100*NonLinear);
code1100:=b1100;
b1100:=round(b1100/psa1100); //пересчет в милливольты
end;
//===============================================
//процедура полного цикла работы ацп с выдачей
//результата в милливольтах (вещественное значение)
procedure In1100MR;
begin
wr1100; //запись конфигурационного регистра,
//в режиме одиночного преобразования - запуск.
rd1100s; //проверка готовности данных и их считывание
b1100:=b1100+OffsetError;
code1100:=b1100;
if b1100<0 then b1100:=0;
b1100r:=((b1100*NonLinear)/psa1100); //пересчет в милливольты
end;
//===============================================
end.
ADS8325
unit ads8325;
{$Idata}
{$O-}
{$xdata}
interface
procedure in8325;
var
data8325:word;
implementation
uses declare,ports,common;
//*************************************************
//ПОДПРОГРАММА ПРИЕМА ДАННЫХ ОТ АЦП ADS8325
//ПРИНЯТЫЕ ДАННЫЕ РАСПОЛАГАЮТСЯ В R6:R7 и в data8325
//=================================================
{
Для расчета результатов измерений в мВ, если используется
на входе INA159, применяется формула:
Vmv=(Code-32768)/3.2
INA159 укладывает диапазон входных напряжений
+/-10В в диапазон выходных напряжений 48-4048 мВ
при напряжении опоры 4096 мВ, которая одновременно
}
//----------------------------
//ПОДПРОГРАММА ФОРМИРОВАНИЯ ТАКТИРУЮЩЕГО ИМПУЛЬСА
procedure CLK;assembler; //3 0.15
asm
setb LINEACLK //2 0.1
clr LINEACLK //2 0.1
end; //3 0.15
//=================================================
//LINEACLK=P3.0
//LINEDATA=P3.1
//LINECONV=P3.2
//USING 2
procedure IN8325; //3 0.15
label INDATA0;
begin
asm
clr LINEACLK
MOV r6,#0 //2 0.1 MKS
MOV r7,#0 //2 0.1
CLR LINECONV //2 0.1
LCALL CLK //4 0.5
LCALL CLK //4 0.5
LCALL CLK //4 0.5
LCALL CLK //4 0.5
LCALL CLK //4 0.5
LCALL CLK //4 0.5
//LCALL CLK //4 0.5
MOV R2,#16 //2 0.1
INDATA0: setb LINEACLK //2 0.1 \
MOV C,LINEDATA //2 0.1 |
MOV A,r7 //1 0.05 |
RLC A //1 0.05 |
MOV r7,A //1 0.05 \ Цикл 1,2 мкс * 16=19,2 мкс
MOV A,r6 //1 0.05 /
RLC A //1 0.05 |
MOV r6,A //2 0.1 |
clr LINEACLK //2 0.1 |
DJNZ R2,INDATA0 //3 0.15 /
SETB LINECONV //2 0.1
mov data8325,r7 //2 0.1
mov data8325+1,r6 //2 0.1
end; //3 0.15
end;
//При частоте генератора микроконтроллера 20 Мгц
//длительность цикла работы с АЦП составляет 19,2 мкс,
//входная и выходная часть подпрограммы занимают 4,55 мкс,
//то есть вся подпрограмма имеет длительность ~ 23,6 мкс.
//Частота на LINEACLK составляет 1,25 Мгц, на
//LINECONV - примерно 40 кГц.
//================================================
end.
ADS7834
unit ads7834;
{$Idata}
{$O-}
{$xdata}
interface
procedure in7834;
procedure shift;
procedure Read7835;
procedure Volt7835;
procedure Code7835;
procedure MVolt7835;
var
data7834:integer;
implementation
uses declare,ports,common;
var cb:byte;
//*************************************************
//ПОДПРОГРАММА ПРИЕМА ДАННЫХ ОТ АЦП ADS7834
//ПРИНЯТЫЕ ДАННЫЕ РАСПОЛАГАЮТСЯ В R6:R7 и в data7834
//=================================================
//----------------------------
//ПОДПРОГРАММА ФОРМИРОВАНИЯ ТАКТИРУЮЩЕГО ИМПУЛЬСА
procedure CLK;assembler;
asm
SETB LINEACLK
CLR LINEACLK
end;
//=================================================
//LINEACLK=P3.0
//LINEDATA=P3.1
//LINECONV=P3.2
//USING 2
procedure IN7834;
label INDATA0;
begin
asm
MOV r6,#0
MOV r7,#0
CLR LINEACLK
CLR LINECONV
LCALL CLK
LCALL CLK
MOV R2,#12
INDATA0: SETB LINEACLK
MOV C,LINEDATA
MOV A,r7
RLC A
MOV r7,A
MOV A,r6
RLC A
MOV r6,A
CLR LINEACLK
NOP
DJNZ R2,INDATA0
SETB LINECONV
end;
data7834:=ar6;
data7834:=data7834 shl 8;
data7834:=data7834+ar7;
end;
//================================================
procedure Shift;
begin
if cy then cb:=1 else cb:=0;
data7834:=data7834 shl 1;
data7834:=data7834 and $fffe;
data7834:=data7834 or cb;
end;
//================================================
procedure Read7835;
begin
if faver then
begin
aver:=0;
for iw:=1 to 1000 do
begin
loadacc;
if (not linemode) or (not linesave) then exit;
in7834;
asm
mov a,data7834+1
mov c,acc.3
end;
if cy then data7834:=data7834 or %1111000000000000;
aver:=aver+data7834;
end;
data7834:=round(aver/1000);
end
else
begin
in7834;
asm
mov a,data7834+1
mov c,acc.3
end;
if cy then data7834:=data7834 or %1111000000000000;
end;
end;
//================================================
procedure Code7835;
begin
asm
mov a,data7834+1
mov c,acc.3
end;
if cy then data7834:=data7834 or %1111000000000000;
data7834:=round(data7834*1.221);
data7834:=round(data7834*KDADS7835);
end;
//================================================
procedure Volt7835;
begin
read7835;
data7834:=round(data7834*1.221);
valr:=data7834*KDADS7835/1000;
end;
//================================================
procedure MVolt7835;
begin
read7835;
data7834:=round(data7834*1.221);
data7834:=round(data7834*KDADS7835);
end;
//================================================
end.
ADS7835
unit ads7835;
//{$Idata}
{$O-}
//{$xdata}
interface
procedure in7834;
procedure in7835;
var
buf7834:integer;
implementation
uses declare,ports;
//================================================
//ПОДПРОГРАММА ПРИЕМА ДАННЫХ ОТ АЦП ADS7834
//ПРИНЯТЫЕ ДАННЫЕ РАСПОЛАГАЮТСЯ В buf7834
//================================================
//ПОДПРОГРАММА ФОРМИРОВАНИЯ ТАКТИРУЮЩЕГО ИМПУЛЬСА
procedure CLK;
begin
lineaclk:=true;
acc:=acc;
lineaclk:=false;
end;
//----------------------------
procedure IN7834;
begin
buf7834:=0;
lineaclk:=false;
lineconv:=false;
CLK;
CLK;
for i:=1 to 12 do
begin
asm
setb lineaclk
mov c,linedata
mov a,buf7834
rlc a
mov buf7834,a
mov a,buf7834+1
rlc a
mov buf7834+1,a
clr lineaclk
end;
end;
lineconv:=true;
end;
//===============================================
//подпрограмма приема данных от ADS7835
procedure in7835;
begin
in7834;
if (buf7834 and $0800)<>0 then
begin
buf7834:=not(buf7834)+1;
buf7834:=buf7834 and $0fff;
buf7834:=-buf7834;
end;
end;
//-----------------------------------------------
end.
ADS7888
unit ads7888;
{$O-}
{$xdata}
{$idata}
interface
//ПОДПРОГРАММА ЧТЕНИЯ ADS7888
var ref7888:word idata;
buf7888:word;
//cs7888:boolean absolute $a0;
//clk7888:boolean absolute $a1;
//sdo7888:boolean absolute $a2;
procedure in7888;
procedure in7888mv;
implementation
uses declare,ports;
//------------------------------------------------
procedure clock7888;assembler;
asm
CLR CLK7888
NOP
SETB CLK7888
end;
//------------------------------------------------
procedure in7888;assembler;
label IN78880,IN78881,IN78882;
asm
clr a
mov buf7888,a
mov buf7888+1,a
CLR CS7888
MOV R2,#4
IN78880: LCALL CLOCK7888
DJNZ R2,IN78880
CLR A
MOV R2,#8
IN78881: MOV C,SDO7888
RLC A
LCALL CLOCK7888
DJNZ R2,IN78881
MOV R2,#4
IN78882: LCALL CLOCK7888
DJNZ R2,IN78882
SETB CS7888
mov buf7888,a
end;
//------------------------------------------------
procedure in7888mv;
begin
IN7888;
vall:=buf7888;
buf7888:=trunc((vall * ref7888) / 256);
end;
//------------------------------------------------
end.