АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Поклонники продукции Microchip Technology Inc тусуются тут.
Frosty85
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср окт 22, 2014 04:24:01

АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение Frosty85 »

Доброго времени, подскажите как считать одним значением данные два регистра ADRESL и ADREHL

Есть переменная:
unsigned long tmp;

Есть формула:
tmp = (long)((float)(tmp/ADC));

где ADC - значение АЦП из двух регистров (ADRESL и ADREHL)
должно принимать значение от 1\25.6 до 25.6 (0-1023)

совсем запутался в этих преобразованиях
Реклама
Мишаня86
Первый раз сказал Мяу!
Сообщения: 21
Зарегистрирован: Чт окт 20, 2011 13:28:56
Откуда: Санкт-Петербург
Контактная информация:

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение Мишаня86 »

Да по-разному можно, я обычно так делаю, в шапке объявляю:
union
{
struct {
unsigned char lo;
unsigned char hi;
}st;
unsigned int adc;
}data;

В коде это выглядит например так:

// производим измерение АЦП каждые 10 мс
GODONE=1;//запускаем преобразование
do{
}while ( GODONE);//ждем завершения приобразования
data.st.hi=ADRESH;
data.st.lo=ADRESL;
data.adc/=5; и т.д. В твоем случае data.adc - это и будет ADC
Реклама
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15571
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение BOB51 »

:shock:
АЦП у pic12f629???
:facepalm:
Мишаня86
Первый раз сказал Мяу!
Сообщения: 21
Зарегистрирован: Чт окт 20, 2011 13:28:56
Откуда: Санкт-Петербург
Контактная информация:

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение Мишаня86 »

BOB51 прав!! У этого крохи PIC12F629 нет АЦП!!! А то я скинул кусок кода, а в даташит некогда было глянуть.
Реклама
Эиком - электронные компоненты и радиодетали
Frosty85
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср окт 22, 2014 04:24:01

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение Frosty85 »

Прошу прощения, все верно PIC12f629 идет без АЦП а PIC12f675 с АЦП
не тот контроллер указал в теме. Как изменить не знаю
Реклама
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15571
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение BOB51 »

Так вроде обработку двухбайтовой величины никто не отменял...
Есть еще опцион "левого/правого выравнивания" результата, естественно с "некоторыми потерями".
К сожалению под СИ не советчик...
8)
Реклама
Frosty85
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср окт 22, 2014 04:24:01

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение Frosty85 »

Спасибо Мишаня86, твой код помог. теперь у меня есть значения от 0 до 1023 как мне их привязать к числу от 1/25 до 25/1
Аватара пользователя
botchin
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Чт дек 27, 2012 20:46:09
Откуда: Болгария, г. Лом

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение botchin »

Frosty85, посколько тебе нужнъ только состояния с 1/25,6 до 25,6 - в сумме 256 значения, то можно обоитись только считъвание старшего бита ADRESH и лево въравниванием резултата ADFM=0 (теряем 4 младших бита - тъ их так и так потеряеш. Зачем брать их если потом сразу будем делить на 4)

Я в асемблере ето сделал бъ с простъм перемещение десятъчной точкой идникатора.
Лом - ето город в Болгарии, а не инструмент юстировки електроники.
Frosty85
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср окт 22, 2014 04:24:01

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение Frosty85 »

:kill: все мой мозг анально порабощен, я не знаю как мне связать эти два значения.

есть формула tmp = (long)((float)(tmp/ADC)) где ADC принимает значения от 51.1 до 1/51.1 как мне их привязать к значениям АЦП от 0 до 1023

уже думаю просто создать массив на 1024 значения и каждый раз выдергивать от туда значение при соответствующем значении с АЦП

примерно так:

tmp = (long)((float)(tmp/a))

array[1024] = {51.1 , 51, 50.9, 50.8,....,0.019646365, 0.019607843, 0.019569472}

a = array[adc]
Аватара пользователя
botchin
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Чт дек 27, 2012 20:46:09
Откуда: Болгария, г. Лом

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение botchin »

Я не могу понять в чем проблема?
Оставь пока формулу и обьясни словами что тъ хочешь получить?

Если возмем старшъе 9 битов АЦП (только их) и разделим на 10 то получим как раз етого ряда 0, 0.1, 0.2 ...... 51.1 Если нам нужен обратнъй ряд то инвертируем АЦП
А ~= A; делим на 10 и получаем 51.1, 51.0 .... 0.1,0
Frosty85 писал(а):ADC принимает значения от 51.1 до 1/51.1
При 9 значущих битах ADC примет значения с 0 до 511

Я не понимаю...
Лом - ето город в Болгарии, а не инструмент юстировки електроники.
Frosty85
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср окт 22, 2014 04:24:01

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение Frosty85 »

дословно я собираю делитель/множитель частоты. На АЦП я пытаюсь реализовать изменяющийся коэффициент деления/умножения. Т.е. на резисторе относительно среднего положения влево - коэфф. деления, а вправо - коэфф. умножение.
Vano79
Открыл глаза
Сообщения: 60
Зарегистрирован: Пт янв 11, 2013 10:54:43

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение Vano79 »

Frosty85 писал(а):array[1024] = {51.1 , 51, 50.9, 50.8,....,0.019646365, 0.019607843, 0.019569472}
Что за дикие числа? Определитесь сколько знаков после запятой необходимо. И необходим ли вообще тип float. Что происходит с данными далее?
Аватара пользователя
botchin
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Чт дек 27, 2012 20:46:09
Откуда: Болгария, г. Лом

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение botchin »

Вам можеть бъть такой алгоритм:
1. Проверяем старшего бита если он=0 то будем делить
-- инвертируем остальнъе (без старшего)
-- получаем резултат с деления
! 1. старшии бит = 1
-- умножаем
-- получаем результат умножения

Или наоборот (с инвертированием) зависить от реализиции.
Лом - ето город в Болгарии, а не инструмент юстировки електроники.
Vano79
Открыл глаза
Сообщения: 60
Зарегистрирован: Пт янв 11, 2013 10:54:43

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение Vano79 »

Frosty85 писал(а):Т.е. на резисторе относительно среднего положения влево - коэфф. деления, а вправо - коэфф. умножение.
И? if (adc < 511)
tmp = (tmp*10)/(511-ADC)
иначе
tmp = (tmp*(ADC-512))/10
Frosty85
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср окт 22, 2014 04:24:01

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение Frosty85 »

Все я окончательно запутался ))))))

Код: Выделить всё


volatile unsigned long   Per_In=0;
unsigned long per_tmp;
unsigned long adc_tmp;

union
{
struct {
unsigned char lo;
unsigned char hi;
}st;
unsigned int adc;
}data;

adc_tmp=data.adc;
per_tmp = Per_In;
per_tmp/=2;

if(per_tmp){
				if (data.adc<=511)
				{adc_tmp=adc_tmp/10;}
				else {adc_tmp= 1/((adc_tmp-511)/10);}
				
            per_tmp = (long)((float)(per_tmp/data.adc));
                }
Аватара пользователя
botchin
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Чт дек 27, 2012 20:46:09
Откуда: Болгария, г. Лом

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение botchin »

Давайте распутъватся.
Frosty85 писал(а):влево - коэфф. деления, а вправо - коэфф. умножение.
Значить у нас три положении:
1. - резистор в точь в середине ADC 512 - умножать и делить не будем
2. - в лево ADC меньше 512 будем делить
--- в зависимости от положение ротора если ротор близок к середине то, очевидно, нам нужно делить на меньшии коефициент
--- если ротор в крайне левое положение (ADC = 0) то очевидно нужно делить на 511/10
-------- из верхних получаем коефициент деления k=(512-ADC)/10 !!!!! посколько возможен вариант k=0 то взять меръ по предовращение етого

3. - в право ADC больше 512 будем умножать на разницу k=(ADC-512)/10 - если ADC 1023 то получим и самъй большой коефициент 511/10

Код: Выделить всё

volatile unsigned long   Per_In=0;
unsigned long per_tmp;
unsigned long adc_tmp;

unsigned int k;	/* новая переменная */

union
{
struct {
unsigned char lo;
unsigned char hi;
}st;
unsigned int adc;
}data;

adc_tmp=data.adc;
per_tmp = Per_In;
per_tmp/=2;

if(per_tmp){
        if (data.adc <= 511){
	k = 512-data.adc;
/* делим что-то на етого коефициента k и делим на 10
для нуля:
в if (condition) проверяем меньше ли 511 значить самое маленькое число которое можеть получится ето 512-511=1 - больше нуля*/
	}
        else{
	k = data.adc - 511;   /*если ADC=512 (середина) то k=1 будем умножать по 1 */
/* умножаем что-то по етого коефициента k и делим на 10*/
	}
 
                }
Попробуй

Остался вопрос про деление на 10. На мой взгляд оно должно бъть после умножение/деление на етого коефициента. Я о том что если разделить коефициента до умножение/деление на 10 то вожножна ситуация когда делим на 0,1 и умножаем на 0,1.
Da-a-a. Здесь вопрос получился .....
Лом - ето город в Болгарии, а не инструмент юстировки електроники.
Frosty85
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср окт 22, 2014 04:24:01

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение Frosty85 »

Спойлер

Код: Выделить всё

#include "pic.h"
__CONFIG ( WDTDIS & INTIO & MCLREN & UNPROTECT );
/****************************************************************/
#define PIN_OUT     GPIO0       // Выходной ПИН
#define TRIS_OUT    TRISIO0     //
#define adc_bits 10 
#define adc_clock 3 
#define adc_sampleus 50 
/****************************************************************/
unsigned long per_tmp;
unsigned int k;
/****************************************************************/
volatile unsigned long   Per_In=0;       // Преобразованный период входного сигнала
static bit               In_Fl=0;        // Флаг окончания преобразования периода
volatile unsigned long   Per_Out=0;      // Период выходного сигнала
/****************************************************************/
union
{
struct {
unsigned char lo;
unsigned char hi;
}st;
unsigned int adc;
}data;

/****************************************************************/
void interrupt _isr(void){
static bit p_fl=0;                      // Флаг преобразования входного периода
static unsigned int     H_Per_In=0;     // Старшие байты вх. периода
static unsigned char    H_Per_Out=0;    // Старший байт вых. периода
//-------------------------------------//
    if(INTF){
        INTF=0;
            if(!p_fl){
                p_fl=1;
                TMR0=0;
                H_Per_In=0;
            }
            else{
                *((char*)&Per_In)=TMR0+5;
                TMR0=0;
                    if(T0IF)                // Если было переполнение
                        H_Per_In++;         // обрабатываем его
                *((int*)((char*)&Per_In+1))=H_Per_In;
                H_Per_In=0;
                In_Fl=1;    // Ставим флаг окончания преобразования
            }
        T0IF=0;
    }
//-------------------------------------//
    if(T0IF && T0IE){
        T0IF = 0;
        H_Per_In++;                         //  +256
            if( *((char*)&H_Per_In+1)>=16 ){    //  >=16*65536 ~1000000 МЦ
                H_Per_In=0;
                p_fl=0;     // Сброс флага преобразования
                Per_In=0;   // Период = 0
                In_Fl=1;    // Ставим флаг окончания преобразования
            }
    }
//-------------------------------------//
    if(TMR1IF && TMR1IE){
    TMR1IF=0;
        if(!H_Per_Out--){
            TMR1 -= *((int*)((char*)&Per_Out));
            H_Per_Out = *((char*)&Per_Out+2);
            PIN_OUT=!PIN_OUT;
        }
    }
//-------------------------------------//

}
/****************************************************************/
void main(){

CMCON=7;        // Настраиваем порты как цифровые
ADCON0=135;
ANSEL=50;

TRIS_OUT=0;
PIN_OUT=0;

T0CS =0;
PSA=1;
PS2=0;
PS1=0;
PS0=0;
TMR0 = 0;
T0IE =1;

TMR1ON=1;
TMR1IE=0;

INTE=1;
INTEDG=0;

PEIE=1;
GIE=1;

Per_Out=0;

while(1){

// производим измерение АЦП каждые 10 мс
ADCON0 |= 0b00000010;
     while(ADCON0 & 0b00000010);
data.st.hi=ADRESH;
data.st.lo=ADRESL;

   if(In_Fl){
        In_Fl=0;
        //--------------------
        GIE=0;
        per_tmp = Per_In;
        GIE=1;
        per_tmp/=2;
        //--------------------
        if(per_tmp){
        if (data.adc <= 511){k = 512-data.adc;}
        else{k = data.adc - 511;}
 			
            per_tmp = (long)((float)(per_tmp/k));
            GIE=0;
            Per_Out = per_tmp;
            GIE=1;
            TMR1IE=1;
        }
        else{
            TMR1IE=0;
            PIN_OUT=0;
        }
    }
 }
}
/****************************************************************/
Изначально все устраивало, зашел ручками нужный коэф. забил, собрал прошивку и залил в МК. Но когда приходиться по 15-20 раз изменять этот коэф., времени убивается столько что всякое желание работать дальше пропадает. Вот и решил дописать в коде вариант с подстроечным резистором на входе АЦП для регулировки коэф.

В исходном варианте был просто #define k 0.66 (или 1 или 0.033) в зависимости что нужно получить множитель или делитель.
Последний раз редактировалось Frosty85 Чт май 19, 2016 14:02:15, всего редактировалось 2 раза.
Аватара пользователя
botchin
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Чт дек 27, 2012 20:46:09
Откуда: Болгария, г. Лом

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение botchin »

Я заменил float k на unsigned int k.

.

Здесь другая проблема возникает. Диапазон ADC 512 +/- 10. Етот диапазон каким-то образом нужно свести к нормалной стойности. А то получается делим и получаем больше (к=0.1)
Лом - ето город в Болгарии, а не инструмент юстировки електроники.
Frosty85
Встал на лапы
Сообщения: 84
Зарегистрирован: Ср окт 22, 2014 04:24:01

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение Frosty85 »

Код: Выделить всё

Memory Summary:
    Program space        used   231h (   561) of   400h words   ( 54.8%)
    Data space           used    35h (    53) of    40h bytes   ( 82.8%)
    EEPROM space         used     0h (     0) of    80h bytes   (  0.0%)
    Configuration bits   used     1h (     1) of     1h word    (100.0%)
    ID Location space    used     0h (     0) of     4h bytes   (  0.0%)
Скомпилировался.

в итоге имеем следующее: от 0 до 50% - значение k от 1 до 51
от 51 до 100% - значение k от 1 до 51 (т.е. повторяется)
Аватара пользователя
botchin
Поставщик валерьянки для Кота
Сообщения: 2029
Зарегистрирован: Чт дек 27, 2012 20:46:09
Откуда: Болгария, г. Лом

Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL

Сообщение botchin »

Заметь что я переправил код что дал
k = 512-data.adc;
/* делим что-то на етого коефициента k и делим на 10
k = data.adc - 511; /*если ADC=512 (середина) то k=1 будем умножать по 1 */
/* умножаем что-то по етого коефициента k и делим на 10*/

т.е. мъ умножение и деление въполняем как разнъе операции и на разнъх местах в теле IF()

А у тебя вне if() и только деление
per_tmp = (long)((float)(per_tmp/k));


У нас проблема будет возле ADC +/- 10. Там коефициент получается .....???!!!!

Если сделаем так:
k = 512-data.adc;
k = k - (k-1)*.9;

то тогда к в диапазоне 1 - 511 будеть изменятся с 1 до 52 и уже не будет unsigned int
Последний раз редактировалось botchin Чт май 19, 2016 14:07:54, всего редактировалось 1 раз.
Лом - ето город в Болгарии, а не инструмент юстировки електроники.
Ответить

Вернуться в «PIC»