Полная версия этой страницы:
Вопросы по ADuC7061
Здравствуйте! Никак не удается запустить АЦП в ADuC7061. В регистре ADCSTA постоянно установлен бит ADC0CERR. Бит завершения преобразования ADC0RDY устанавливается, значит АЦП работает. На входе около 1,3В, опроное напряжение выбрано AVDD (2,5В). В чем может быть проблема? Настройка АЦП приведена ниже.
//-------------- Установка необходимой частоты генератора ------------------
POWKEY1 = 0x1;
POWCON0 = 0x78; //Set core to max CPU //speed of 10.24 MHz
POWKEY2 = 0xF4;
//------------- Настройка АЦП -----------------------
// Configure ADC0 for continuous conversions, 1Khz, AIN0 in Single-ended mode
ADCFLT = 0x7; // Chop off, 1Khz samping rate, SF = 7. No averaging
ADCMDE = BIT0 + BIT7; // Continuous Conversion mode, Normal mode, 4Mhz clock source to ADC.
ADC0CON = // Gain = 1, Buffer on.
BIT4 + BIT5 + //(AVDD, AGND) reference
BIT6 + // AIN0 selected in Single ended mode
BIT10 + // Unipolar ADC input
BIT12 + // ------------------------------ опорное напряжение выше 1,35В
BIT15; // Primary channel ADC enable.
ADCCFG = 0;
AHTOXA
Nov 13 2010, 07:45
Цитата(gmp @ Nov 13 2010, 09:36)

На входе около 1,3В, опроное напряжение выбрано AVDD (2,5В). В чем может быть проблема?
...
BIT4 + BIT5 + //(AVDD, AGND) reference
У вас опорное выбрано AVDD/2:
Цитата
5:4 ADC0REF[1:0]
[11] = (AVDD, AGND) divide-by-two selected.
Сконфигурировал на подачу внешней опоры(установил только BIT4) все равно выдает ошибку.
Подал на вход 1В для первого и второго случая, все равно выдает ошибку.
AHTOXA
Nov 13 2010, 15:34
Хм. А куда у вас подключен ADC5?
Никуда не подключен. Он разве не относительно нуля измеряет? Этим контроллером вообще можно измерить напряжение от 0 до 2,2В?
AHTOXA
Nov 14 2010, 07:12
Да фиг его знает. В даташите написано:
Цитата
[0001] = ADC0/ADC5 (single-ended mode).
Может, это значит, что для single-ended каналов ADC5 является землёй? Попробуйте - узнаете
Да пробовал уже, ошибка и все. Попробовал включить дифференциальный режим, что-то зашевелилось, ошибка не выскакивает, переключил обратно и снова ошибка. Причем ошибка выскакивает сразу после конфигурации АЦП.
AHTOXA
Nov 14 2010, 22:25
А с внутренней опорой - работает?
В однополярном режиме от внутренней опоры тоже не работает.
Сегодня скачал Keil, там вообще все по другому работает. Может с дровами к JTAG (miDAS-Link) что не так?
AHTOXA
Nov 15 2010, 15:56
Но программа-то нормально заливается? Сделайте какой-нибудь вывод результатов (типа в UART), и попробуйте без отладчика.
Программа компилится и заливается нормально. В поддержку написал, может что подскажут.
Сегодня наконец-то удалось запустить АЦП. Измерение в однополярном режиме осуществляется относительно ADC5, а не массы, но это еще не все. Выяснилось, что если не отключать питания mIDAS-Link при перезапуске отладки, АЦП сразу инициализируется с ошибкой преобразования и никакие манипуляции не дают эффекта. Если при перезапуске отладки переподать питание на плату и только потом подключить mIDAS-Link, то все регистры инициализируются нулями и все нормально работает. Вот такая странность.....
Теперь нужно заставить АЦП измерять напряжение до 2,2В (сейчас только 1,2В), запустить UART и добиться, чтобы в IAR срабатывали прерывания.
Кстати о прерываниях. Они описаны в программе и разрешены, в регистрах высталяются биты, что прерывание произошло, но перехода в обработку прерывания не происходит, может какой файл нужно подключить?
Сергей Борщ
Nov 17 2010, 07:46
QUOTE (gmp @ Nov 17 2010, 07:06)

в регистрах высталяются биты, что прерывание произошло,
А посмотрите внимательно описание - чтение этих битов (в том числе и отладчиком) не приводит к их сбросу? В некоторых ARMах прерывания не работатют если в отладчике открыто окно с регистрами контроллера прерываний.
Если вы про окно "Register", то перехода на обработку прерывания не происходит, хоть при открытом, хоть при закрытом окне. Может где-то нужно вектора прописывать? Кусок с прерываниями взял из примера.
Вотподключенные файлы и разрешение прерываний:
#include <Analogdevices/ioaduc7061.h>
# include "stdio.h"
# include "string.h"
#include <intrinsics.h>
IRQEN = BIT10 + BIT11; // Enable ADC and UART interrupts
Вот описание обработки, но IAR сюда не переходит:
__irq __arm void IRQ_Handler(void)
{
unsigned long IRQSTATUS = 0;
unsigned char ucCOMIID0 = 0;
IRQSTATUS = IRQSTA; // Read off IRQSTA register
if ((IRQSTATUS & BIT11) == BIT11) //UART interrupt source
{
ucCOMIID0 = COMIID0;
if ((ucCOMIID0 & 0x2) == 0x2) // Transmit buffer empty
{
ucTxBufferEmpty = 1;
}
}
if ((IRQSTATUS & BIT10) == BIT10) //If ADC0 interrupt source
{
ulADC0Result = ADC0DAT; // Read ADC0 conversion result
bSendResultToUART = 1;
}
}
Сергей Борщ
Nov 17 2010, 11:12
QUOTE (gmp @ Nov 17 2010, 11:40)

Может где-то нужно вектора прописывать? Кусок с прерываниями взял из примера.
Понятия не имею как в последних версиях, в 4.хх надо было перед вектором прописывать #pragma vector. А что у вас дизассемблер отладчика показывает по адресу вектора IRQ (0x18)? И если на этот адрес поставить точку останова - туда программа попадает? Глобально прерывания разрешены (бит I в CPSR)?
Добавил #pragma vector = 0x18, если на этот адрес поставить точку останова - туда программа НЕ попадает. Бит I в CPSR установлен в 1, хотя я его не устанавливал. Куда еще глянуть?
Сергей Борщ
Nov 18 2010, 11:31
QUOTE (gmp @ Nov 18 2010, 05:15)

Бит I в CPSR установлен в 1, хотя я его не устанавливал. Куда еще глянуть?
Для начало в описание ядра ARM7, там написано что 1 в бите I означает "прерывания глобально запрещены в ядре" и оно в таком состоянии оказывается каждый раз после сброса. Потом гляньте описание компилятора на предмет функции enable_interrupt().
Да, спасибо, я уже проделал данные манипуляции (добавил функцию enable_interrupt()). Но в ломаной версии IAR5, прерывания не заработали. Скачал новый v. 6.10, 32K Kickstart Edition. Там прерывания заработали.
Кстати, как вы и говорили, если в дебагере смотреть регистры прерывания, то получаются некорректные результаты. И в обработчике прерывания нужно обязательно прописывать #pragma vector = 0x18, иначе не работает, хотя в примерах от самого IAR нет ни enable_interrupt(), ни #pragma vector = 0x18.
Теперь настраиваю UART в 8-ми битном режиме, потом нужно будет как-то 9-ти битный режим запускать. Пока из массива в несколько байт, UART передает только первые 2 и умолкает.
Сергей Борщ
Nov 18 2010, 13:42
QUOTE (gmp @ Nov 18 2010, 15:28)

Кстати, как вы и говорили, если в дебагере смотреть регистры прерывания, то получаются некорректные результаты.
Да, потому что чтение некоторых из этих регистров может изменять их значения (неважно какое чтение - ядром или отладчиком).
QUOTE (gmp @ Nov 18 2010, 15:28)

И в обработчике прерывания нужно обязательно прописывать #pragma vector = 0x18, иначе не работает, хотя в примерах от самого IAR нет ни enable_interrupt(), ни #pragma vector = 0x18.
Обработчики прерываний можно оформлять разными способами. Посмотрите здесь:
http://electronix.ru/forum/index.php?showt...mp;#entry191159QUOTE (gmp @ Nov 18 2010, 15:28)

Пока из массива в несколько байт, UART передает только первые 2 и умолкает.
Не видя кода подсказать могут разве что очень продвинутые телепаты.
Цитата(Сергей Борщ @ Nov 18 2010, 18:42)

Не видя кода подсказать могут разве что очень продвинутые телепаты.
Да я понимаю, просто в данный момент программы нет под рукой

))
Привожу текст программы, которую сейчас ковыряю. Данная программа взята из примеров, но почему-то без дополнительных костылей не работает. Как уже говорил ранее, UART отсылает первые 2 байта из массива szTemp[] и умолкает, хотя прерывания генерируются.
CODE
// Bit Definitions
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
#define BIT8 0x100
#define BIT9 0x200
#define BIT10 0x400
#define BIT11 0x800
#define BIT12 0x1000
#define BIT13 0x2000
#define BIT14 0x4000
#define BIT15 0x8000
#include <Analogdevices/ioaduc7061.h>
# include "stdio.h"
# include "string.h"
#include <intrinsics.h>
#include <arm_interrupt.h>
volatile unsigned char bSendResultToUART = 0; // Flag used to indicate ADC0 resutl ready to send to UART
unsigned char szTemp[16] = ""; // Used to store ADC0 result before printing to UART
unsigned char ucTxBufferEmpty = 0; // Used to indicate that the UART Tx buffer is empty
volatile unsigned long ulADC0Result = 0; // Variable that ADC0DAT is read into in ADC0 IRQ
float V;
int main(void)
{
unsigned char i = 0;
unsigned char nLen = 0;
POWKEY1 = 0x1;
POWCON0 = 0x78; // Set core to max CPU speed of 10.24Mhz
POWKEY2 = 0xF4;
// Initialize the UART for 9600-8-N
GP1CON = BIT0 + BIT4; // Select UART functionality for P1.0/P1.1
COMCON0 = BIT7; // Enable access to COMDIV registers
COMDIV0 = 0x21; // Set baud rate to 9600.
COMDIV1 = 0x00;
//COMDIV2 = 0x21 + BIT11; // Enable fractional divider for more accurate baud rate setting
COMCON0 = BIT0 + BIT1 + BIT2;
COMIEN0 = BIT0 + BIT1; // Enable UART interrupts when Rx full and Tx buffer empty.
// Configure ADC0 for continuous conversions, 1Khz, AIN0 in Single-ended mode
ADCMSKI = BIT0; // Enable ADC0 result ready interrupt source
ADCFLT = 0x7; // Chop off, 1Khz samping rate, SF = 7. No averaging
ADCMDE = BIT0 + BIT7; // Continuous Conversion mode, Normal mode, 4Mhz clock source to ADC.
ADC0CON =
BIT4 +
BIT6 + BIT7 + BIT8 + // AIN0 selected in Single ended mode
BIT10 + // Unipolar ADC output
BIT15; // Gain = 1, Buffer on. Also, Int reference,
ADCCFG = 0;
IRQEN = BIT10 + BIT11; // Enable ADC and UART interrupts
__enable_interrupt();
bSendResultToUART = 0;
while (1)
{
if (bSendResultToUART == 1) // Is there an ADC0 result ready for UART transmission?
{
sprintf ( (char*)szTemp, "%lu\r",ulADC0Result ); // Send the ADC0 Result to the UART
nLen = strlen((char*)szTemp);
for ( i = 0 ; i < nLen ; i++ ) // loop to send ADC0 result
{
COMTX = szTemp[i];
ucTxBufferEmpty = 0;
while (ucTxBufferEmpty == 0)
}
}
}
}
#pragma vector = 0x18
__irq __arm void IRQ_Handler(void)
{
unsigned long IRQSTATUS = 0;
unsigned char ucCOMIID0 = 0;
IRQSTATUS = IRQSTA; // Read off IRQSTA register
if ((IRQSTATUS & BIT11) == BIT11) //UART interrupt source
{
ucCOMIID0 = COMIID0;
if ((ucCOMIID0 & 0x2) == 0x2) // Transmit buffer empty
{
ucTxBufferEmpty = 1;
}
}
if ((IRQSTATUS & BIT10) == BIT10) //If ADC0 interrupt source
{
ulADC0Result = ADC0DAT; // Read ADC0 conversion result
bSendResultToUART = 1;
}
}
Оказалось, причина умолкания UARTа в том, что регистр COMRX нигде не считывался, соответственно, флаг прерывания по приему не сбрасывался и программа крутилась в прерывании по UART. Вот, что добавил:
if ((ucCOMIID0 & 0x4) == 0x4) // Receive buffer empty
{
V=COMRX;
}
Теперь вопрос. Как организовать прием и обработку 9-ого бита данных?
Сергей Борщ
Nov 19 2010, 10:19
QUOTE (gmp @ Nov 19 2010, 06:12)

Привожу текст программы, которую сейчас ковыряю.
1) ucTxBufferEmpty должен быть volatile.
2)
CODE
COMTX = szTemp[i];
ucTxBufferEmpty = 0;
while (ucTxBufferEmpty == 0);
попробуйте переделать в
CODE
ucTxBufferEmpty = 0;
COMTX = szTemp[i];
while (ucTxBufferEmpty == 0);
или
CODE
while (ucTxBufferBusy == 1);
ucTxBufferBusy = 1;
COMTX = szTemp[i];
QUOTE (gmp @ Nov 19 2010, 06:12)

Данная программа взята из примеров
Такими примерами лучше не пользоваться.
QUOTE (gmp @ Nov 19 2010, 06:12)

Теперь вопрос. Как организовать прием и обработку 9-ого бита данных?
Понятия не имею. Может кто-то другой подскажет, или придется вам перечитывать даташит и думать, думать, думать...
Я пример этот взял, чтобы можно было на что-то опираться при обсуждении возникающих вопросов. Мне кажется, что не удобно приводить куски кода с кучей непонятных переменных, а здесь все просто.
Сейчас сделал обработку 9-ого бита. Все работает пока идут запросом, например только четные байты, если приходит нечетный байт, то происходит перенастройка регистра, который определяет установлен ли 9-ый бит. при этом на этот запрос ответа не получаем. На следующий нечетный байт мы нормально отвечаем, это длится пока идут нечетные байты. Картина повторяется при приходе четного байта. Из-за потерь на перенастройку у головного устройства возникают ошибки по неответам - это плохо. Сейчас думаю как все поправить. Код пока не привожу, т.к. там сейчас черт ногу сломит.
Привожу кусок кода с обработкой 9-ого бита, может кому пригодится. Здесь 0x81, 0x3F и 0xC2 это адресные байты, которые мне надо обрабатывать. У вас могут быть свои.
// Initialize the UART for 9600-9-N
GP1CON = BIT0 + BIT4; // Select UART functionality for P1.0/P1.1
COMCON0 = BIT7; // Enable access to COMDIV registers
COMDIV0 = 0x21; // Set baud rate to 9600.
COMDIV1 = 0x00;
COMCON0 = BIT0 + BIT1 + BIT3+BIT4
COMIEN0 = BIT0 + BIT1; // Enable UART interrupts when Rx full and Tx buffer empty.
// Прерывания
#pragma vector = 0x18
__irq __arm void IRQ_Handler(void)
{
unsigned long IRQSTATUS = 0;
unsigned char ucCOMIID0 = 0;
unsigned char ucCOMSTA0 = 0;
unsigned char UDR_t;
IRQSTATUS = IRQSTA; // Read off IRQSTA register
if ((IRQSTATUS & BIT11) == BIT11) //UART interrupt source
{
ucCOMIID0 = COMIID0;
if ((ucCOMIID0 & 0x4) == 0x4) // Receive buffer empty
{
UDR_t=COMRX;
ucCOMSTA0=COMSTA0;
if (((ucCOMSTA0 & 0x4) == 0x4)&&((UDR_t==0x81)||(UDR_t==0x3F))) bit9=1;
else if (((ucCOMSTA0 & 0x4) != 0x4)&&(UDR_t==0xC2)) bit9=1;
else bit9=0;
....................
}
}
}
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.