Цитата(StasUKR @ Mar 12 2013, 17:14)

Не получается найти общий язык с АЦПехой AD7795... =(
глянул тут
http://electronix.ru/forum/index.php?showt...6&hl=ad7792 но не понял в каком смысле дернуть 32 раза?
32 раза моргнуть циклом 1/0 ногой Din?(32 еденицы, 32 нуля в итоге)
Ну вы и докопались, аж до темы 2006-го года

Тут, как и в любом другом деле, важна методология.
1. Убедитесь, что АЦП работает (по дефолту после сброса он вроде бы преобразовывает в цикле, это можно проверить по наличию импульсов на выводе RDY (нужен pull-up подтягивающий резистор!). Если нет импульсов- убедитесь по даташиту, что по ресету состояние регистров соответствует режиму преобразования, вдруг AD что-то поменял в этой модели.
При этом обеспечьте неактивное состояние на SPI интерфейсе от включения и до конца эксперимента, вдруг Вы его куда-то загоняете и поэтому он не преобразовывает.
2. Только если первый уровень игры пройден- переходим ко второму. проверяем связь. Про сброс пачкой импульсов написано в даташите, страница Rev. D | Page 28 of 36:
Цитата
The serial interface can be reset by writing a series of 1s on the DIN input. If a Logic 1 is written to the AD7794/AD7795 line for at least 32 serial clock cycles, the serial interface is reset. This ensures that the interface can be reset to a known state if the interface gets lost due to a software error or some glitch in the system. Reset returns the interface to the state in which it is expecting a write to the communications register. This operation resets the contents of all registers to their power-on values. Following a reset, the user should allow a period of 500 μs before addressing the serial interface.
Вот код из одного старенького проекта про AD7792 (приаттачить файл с расширением "с" не разрешает почему-то, так что прямо сюда и копирую.
там даже выпиливание побитное есть закомментаренное, наверное с времен моих разборок осталось.
CODE
#include <pic18.h>
//#include "pic18cfg.h"
#include "deftype.h"
#include "ad7792_const.h"
#include "PinDef.h"
#include <always.h>
#include "var2_ext.h"
void delay_1ms(void);
void delay_ms(int nms);
u16 ADC_RequestData(u8 codeADCdev);
void delay_halphBit(void);
void initSPI (void);
u8 SPI_tx8bit(u8 txData);
u16 AD7792_RdReg16bit(u8 codeADCdev, u8 nReg);
void AD7792_WrReg16bit(u8 codeADCdev, u8 nReg, u16 wrData);
void AD7792_WrReg8bit(u8 codeADCdev, u8 nReg, u8 wrData);
void delay_1us(void);
void Ad7792_reset(void);
void ADC_Init(void);
void adc_StartCalibrZS(u8 codeADCdev);
void adc_StartCalibrFS(u8 codeADCdev);
void ADC_Init(void)
{
u8 n;
Ad7792_reset();
// delay_ms(20);
//TC_ALL
AD7792_WrReg16bit(DEVCODE_TC_ALL, AD7792_REG_CONFIG, TC_CONFIG);
AD7792_WrReg8bit (DEVCODE_TC_ALL, AD7792_REG_IO, TC_IO);
//TC1
AD7792_WrReg16bit(DEVCODE_TC1, AD7792_REG_CONFIG, TC_CONFIG_FOR_TC1);
AD7792_WrReg16bit(DEVCODE_TC_ALL, AD7792_REG_MODE, TC_MODE);
// delay_ms(300);
/*
//калибровка TC
adc_StartCalibrZS(DEVCODE_TC1);
adc_StartCalibrZS(DEVCODE_TC2);
adc_StartCalibrZS(DEVCODE_TC3);
adc_StartCalibrZS(DEVCODE_TC4);
adc_StartCalibrZS(DEVCODE_TC5);
delay_ms(1000); //время, которого точно хватит на калибровку
adc_StartCalibrFS(DEVCODE_TC1);
adc_StartCalibrFS(DEVCODE_TC2);
adc_StartCalibrFS(DEVCODE_TC3);
adc_StartCalibrFS(DEVCODE_TC4);
adc_StartCalibrFS(DEVCODE_TC5);
delay_ms(2000); //время, которого точно хватит на калибровку
*/
return;
}
void ADC_Init2(void)
{
u8 n;
Ad7792_reset();
//TC
AD7792_WrReg16bit(DEVCODE_TC_ALL, AD7792_REG_CONFIG, TC_CONFIG);
AD7792_WrReg16bit(DEVCODE_TC1, AD7792_REG_CONFIG, TC_CONFIG_FOR_TC1);
AD7792_WrReg8bit (DEVCODE_TC_ALL, AD7792_REG_IO, TC_IO);
AD7792_WrReg16bit(DEVCODE_TC_ALL, AD7792_REG_MODE, TC_MODE);
return;
}
void Ad7792_reset(void)
{
u16 n;
SPICS_TC1 = 0;
SPICS_TC2 = 0;
SPICS_TC3 = 0;
SPICS_TC4 = 0;
SPICS_TC5 = 0;
SPICS_TC6 = 0;
SPICS_TC7 = 0;
SPICS_TC8 = 0;
SPICS_TC9 = 0;
SPICS_TC10= 0;
SPICS_TC11= 0;
SPICS_TC12= 0;
SPICS_TC13= 0;
SPICS_TC14= 0;
SPICS_TC15= 0;
SPI_tx8bit(0xFF);
SPI_tx8bit(0xFF);
SPI_tx8bit(0xFF);
SPI_tx8bit(0xFF);
SPI_tx8bit(0xFF);
SPICS_TC1 = 1;
SPICS_TC2 = 1;
SPICS_TC3 = 1;
SPICS_TC4 = 1;
SPICS_TC5 = 1;
SPICS_TC6 = 1;
SPICS_TC7 = 1;
SPICS_TC8 = 1;
SPICS_TC9 = 1;
SPICS_TC10= 1;
SPICS_TC11= 1;
SPICS_TC12= 1;
SPICS_TC13= 1;
SPICS_TC14= 1;
SPICS_TC15= 1;
for (n = 0; n < 500;n++) delay_1us(); //pause 500us
for (n = 0; n < 500;n++) delay_1us(); //pause 500us
}
void initSPI (void)
{
//выключил все каналы встроенного АЦП PIC
ADCON1 = 0b00000110;
TRISC3 = 0;
TRISC4 = 1;
TRISC5 = 0;
TRIS_SPICS_TC1 = 0;
TRIS_SPICS_TC2 = 0;
TRIS_SPICS_TC3 = 0;
TRIS_SPICS_TC4 = 0;
TRIS_SPICS_TC5 = 0;
TRIS_SPICS_TC6 = 0;
TRIS_SPICS_TC7 = 0;
TRIS_SPICS_TC8 = 0;
TRIS_SPICS_TC9 = 0;
TRIS_SPICS_TC10 = 0;
TRIS_SPICS_TC11 = 0;
TRIS_SPICS_TC12 = 0;
TRIS_SPICS_TC13 = 0;
TRIS_SPICS_TC14 = 0;
TRIS_SPICS_TC15 = 0;
TRIS_SPICS_TC16 = 0;
SPICS_TC1 = 1;
SPICS_TC2 = 1;
SPICS_TC3 = 1;
SPICS_TC4 = 1;
SPICS_TC5 = 1;
SPICS_TC6 = 1;
SPICS_TC7 = 1;
SPICS_TC8 = 1;
SPICS_TC9 = 1;
SPICS_TC10 = 1;
SPICS_TC11 = 1;
SPICS_TC12 = 1;
SPICS_TC13 = 1;
SPICS_TC14 = 1;
SPICS_TC15 = 1;
SPICS_TC16 = 1;
//тактовая SPICLK = TMR2 / 2 = 24 kHz
//TMR2 F= (Fosc /4)/4) / 96 = 2304000 /(pr2+1) Hz = 24 kHz
T2CON = 0b00000101; //presc = 4 //тактовая SPICLK = (((( Fosc /4)/4) / 96))/2 = 12kHz
PR2 = 47;
//при прохождении через оптроны сигналы SPI (кроме CS) инвертируются. Меняем полярность на обратную.
//Также необходимо далее инвертировать биты данных, передаваемых/принимаемых через SPI.
SSPSTAT = 0b00000000;
SSPCON1 = 0b00100011; // TMR2out/2 = 12 kHz
}
void select_ADC_CS(u8 n)
{
// gie_off;
switch (n)
{
case DEVCODE_TC1: SPICS_TC1 = 0; goto end;
case DEVCODE_TC2: SPICS_TC2 = 0; goto end;
case DEVCODE_TC3: SPICS_TC3 = 0; goto end;
case DEVCODE_TC4: SPICS_TC4 = 0; goto end;
case DEVCODE_TC5: SPICS_TC5 = 0; goto end;
case DEVCODE_TC6: SPICS_TC6 = 0; goto end;
case DEVCODE_TC7: SPICS_TC7 = 0; goto end;
case DEVCODE_TC8: SPICS_TC8 = 0; goto end;
case DEVCODE_TC9: SPICS_TC9 = 0; goto end;
case DEVCODE_TC10: SPICS_TC10 = 0; goto end;
case DEVCODE_TC11: SPICS_TC11 = 0; goto end;
case DEVCODE_TC12: SPICS_TC12 = 0; goto end;
case DEVCODE_TC13: SPICS_TC13 = 0; goto end;
case DEVCODE_TC14: SPICS_TC14 = 0; goto end;
case DEVCODE_TC15: SPICS_TC15 = 0; goto end;
case DEVCODE_TC16: SPICS_TC16 = 0; goto end;
case DEVCODE_TC_ALL:
{
SPICS_TC1 = 0;
SPICS_TC2 = 0;
SPICS_TC3 = 0;
SPICS_TC4 = 0;
SPICS_TC5 = 0;
SPICS_TC6 = 0;
SPICS_TC7 = 0;
SPICS_TC8 = 0;
SPICS_TC9 = 0;
SPICS_TC10 = 0;
SPICS_TC11 = 0;
SPICS_TC12 = 0;
SPICS_TC13 = 0;
SPICS_TC14 = 0;
SPICS_TC15 = 0;
SPICS_TC16 = 0;
goto end;
}
default: return;
}
end:;
delay_halphBit();
delay_halphBit();
return;
}
void unselect_ADC_CS(u8 n)
{
SPICS_TC1 = 1;
SPICS_TC2 = 1;
SPICS_TC3 = 1;
SPICS_TC4 = 1;
SPICS_TC5 = 1;
SPICS_TC6 = 1;
SPICS_TC7 = 1;
SPICS_TC8 = 1;
SPICS_TC9 = 1;
SPICS_TC10 = 1;
SPICS_TC11 = 1;
SPICS_TC12 = 1;
SPICS_TC13 = 1;
SPICS_TC14 = 1;
SPICS_TC15 = 1;
SPICS_TC16 = 1;
delay_halphBit();
delay_halphBit();
}
//Запись в 8-битный регистр
void AD7792_WrReg8bit(u8 codeADCdev, u8 nReg, u8 wrData)
{
u8 tmp;
select_ADC_CS(codeADCdev);
//запись в Communications Register
tmp = (0<<7) //WEN
|(0<<6) //R/W
|((nReg&0x07)<<3) //RS2..RS0
|(0<<2); //CREAD
SPI_tx8bit(tmp);
//запись данных в регистр
SPI_tx8bit(wrData);
unselect_ADC_CS(codeADCdev);
}
//Запись в 16-битный регистр
void AD7792_WrReg16bit(u8 codeADCdev, u8 nReg, u16 wrData)
{
u8 tmp;
select_ADC_CS(codeADCdev);
//запись в Communications Register
tmp = (0<<7) //WEN
|(0<<6) //R/W
|((nReg&0x07)<<3) //RS2..RS0
|(0<<2); //CREAD
SPI_tx8bit(tmp);
//запись данных в регистр
SPI_tx8bit((u8)(wrData>>8)); //MSB
delay_halphBit();
SPI_tx8bit((u8)(wrData)); //LSB
unselect_ADC_CS(codeADCdev);
}
//чтение 16-битного регистра
u16 AD7792_RdReg16bit(u8 codeADCdev, u8 nReg)
{
u8 tmp;
u16_2u8 tmp16;
select_ADC_CS(codeADCdev);
//запись в Communications Register
tmp = (0<<7) //WEN
|(1<<6) //R/W
|((nReg&0x07)<<3) //RS2..RS0
|(0<<2); //CREAD
SPI_tx8bit(tmp);
//чтение данных (передается мусор)
tmp16._u8[1] = SPI_tx8bit(0xFF);
tmp16._u8[0] = SPI_tx8bit(0xFF);
unselect_ADC_CS(codeADCdev);
return tmp16._u16;
}
//чтение 8-битного регистра
u8 AD7792_RdReg8bit(u8 codeADCdev, u8 nReg)
{
u8 tmp, tmp8H;
select_ADC_CS(codeADCdev);
//запись в Communications Register
tmp = (0<<7) //WEN
|(1<<6) //R/W
|((nReg&0x07)<<3) //RS2..RS0
|(0<<2); //CREAD
SPI_tx8bit(tmp);
//чтение данных (передается мусор)
tmp8H = SPI_tx8bit(0x00);
unselect_ADC_CS(codeADCdev);
return tmp8H;
}
//передача байта в SPI
//выход: принятый байт
u8 SPI_tx8bit(u8 txData)
{
SSPIF = 0;
SSPBUF = txData^0xff; ////при прохождении через оптроны сигналы SPI инвертируются.
while (SSPIF == 0); //ждем окончания передачи
return SSPBUF ^ 0xff; //читаем принятый байт //при прохождении через оптроны сигналы SPI (кроме CS) инвертируются.
/*
//выпиливаем побитно
u8 rxdata = 0;
u8 txdata = txData^0xff;
u8 n;
delay_1us();
delay_1us();
delay_1us();
delay_1us();
delay_1us();
for (n = 0; n < 8; n++)
{
delay_halphBit();
PIN_SCLK = 1;
//прием
rxdata = rxdata << 1;
if (PIN_MISO != 0) rxdata = rxdata | 0x01;
//передача
delay_halphBit();
PIN_SCLK = 0;
if ((txdata & 0x80)==0) PIN_MOSI=0;
else PIN_MOSI=1;
txdata = txdata << 1;
}
return rxdata^0xff;
*/
}
void delay_halphBit(void)
{ //170us
int n;
for (n = 0; n < 50; n++) delay_1us();
}
void delay_1us(void)
{
#asm
// nop;
// nop;
// nop;
// nop
nop;
nop;
nop;
nop;
nop;
#endasm
return;
}
u16 ADC_RequestData(u8 codeADCdev)
{
u16_2u8 rez;
delay_ms(5);
select_ADC_CS(codeADCdev);
delay_ms(20);
//команда на старт АЦП
SPI_tx8bit(0x08);
SPI_tx8bit(0x20); //MSB
SPI_tx8bit(0x0F); //LSB
//пауза 0.5 сек.
unselect_ADC_CS(codeADCdev);
delay_ms(1000);
select_ADC_CS(codeADCdev);
//команда на чтение данных
SPI_tx8bit(0x58);
//чтение данных (передается мусор)
delay_ms(1);
rez._u8[1] = SPI_tx8bit(0x00);
delay_ms(1);
rez._u8[0] = SPI_tx8bit(0x00);
delay_ms(1);
SPI_tx8bit(0x58);
delay_ms(1);
rez._u8[1] = SPI_tx8bit(0x00);
delay_ms(1);
rez._u8[0] = SPI_tx8bit(0x00);
unselect_ADC_CS(codeADCdev);
return rez._u16;
}
//задержка на указанное кол-во ms
void delay_1ms(void)
{
int n;
for (n = 0; n < 420; n++) delay_1us();
return;
}
//задержка на указанное кол-во ms
void delay_ms(int nms)
{
int n;
for (n = 0; n < nms; n++) delay_1ms();
return;
}
//запуск калибровки Zero-Scale указанного АЦП
void adc_StartCalibrZS(u8 codeADCdev)
{
AD7792_WrReg16bit(codeADCdev, AD7792_REG_MODE, TC_MODE_CALIBR_ZS);
}
//запуск калибровки Full-Scale указанного АЦП
void adc_StartCalibrFS(u8 codeADCdev)
{
AD7792_WrReg16bit(codeADCdev, AD7792_REG_MODE, TC_MODE_CALIBR_FS);
}
extern void init_userTask(void);
volatile u16 Debug2;
volatile u16 Debug3;
//проверка валидности конфигурации регистров АЦП и переинициализация, если нужно.
void check_ADC_Regs(u8 codeADCdev)
{
if (DEVCODE_TC1 == codeADCdev)
{
Debug2 = AD7792_RdReg16bit(codeADCdev, AD7792_REG_CONFIG);
if (TC_CONFIG_FOR_TC1 != Debug2)
{//вторая попытка чтения регистра
Debug2 = AD7792_RdReg16bit(codeADCdev, AD7792_REG_CONFIG);
Debug3 = AD7792_REG_CONFIG;
if (TC_CONFIG_FOR_TC1 != Debug2) goto err;
}
}
else
{
Debug2 = AD7792_RdReg16bit(codeADCdev, AD7792_REG_CONFIG);
if (TC_CONFIG != Debug2)
{//вторая попытка чтения регистра
Debug2 = AD7792_RdReg16bit(codeADCdev, AD7792_REG_CONFIG);
Debug3 = AD7792_REG_CONFIG;
if (TC_CONFIG != Debug2) goto err;
}
}
Debug2 = AD7792_RdReg8bit(codeADCdev, AD7792_REG_IO);
if (TC_IO != Debug2)
{//вторая попытка чтения регистра
Debug2 = AD7792_RdReg8bit(codeADCdev, AD7792_REG_IO);
Debug3 = AD7792_REG_IO;
if (TC_IO != Debug2) goto err;
}
return; //OK
//нужна переинициализация
err:;
nErr_ADC[codeADCdev] ++;
// #asm
// nop;
// nop;
// #endasm
ADC_Init();
init_userTask();
}
P.S. Кстати, бытует мнение, что техника работает лучше, если к ней относится как к чему-то разумному. Ну, не любит оно когда его как-то неуважительно или непривычно называют. У меня один знакомый процессор называет не иначе как "профессор", ну те и отвечают ему взаимностью. А на "АЦПху" оно и обидится может, вдруг у Вас тот самый случай, мстит оно Вам