АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
Доброго времени, подскажите как считать одним значением данные два регистра ADRESL и ADREHL
Есть переменная:
unsigned long tmp;
Есть формула:
tmp = (long)((float)(tmp/ADC));
где ADC - значение АЦП из двух регистров (ADRESL и ADREHL)
должно принимать значение от 1\25.6 до 25.6 (0-1023)
совсем запутался в этих преобразованиях
Есть переменная:
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
Да по-разному можно, я обычно так делаю, в шапке объявляю:
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
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
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
АЦП у pic12f629???
-
Мишаня86
- Первый раз сказал Мяу!
- Сообщения: 21
- Зарегистрирован: Чт окт 20, 2011 13:28:56
- Откуда: Санкт-Петербург
- Контактная информация:
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
BOB51 прав!! У этого крохи PIC12F629 нет АЦП!!! А то я скинул кусок кода, а в даташит некогда было глянуть.
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
Прошу прощения, все верно PIC12f629 идет без АЦП а PIC12f675 с АЦП
не тот контроллер указал в теме. Как изменить не знаю
не тот контроллер указал в теме. Как изменить не знаю
- Реклама
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
Так вроде обработку двухбайтовой величины никто не отменял...
Есть еще опцион "левого/правого выравнивания" результата, естественно с "некоторыми потерями".
К сожалению под СИ не советчик...

Есть еще опцион "левого/правого выравнивания" результата, естественно с "некоторыми потерями".
К сожалению под СИ не советчик...
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
Спасибо Мишаня86, твой код помог. теперь у меня есть значения от 0 до 1023 как мне их привязать к числу от 1/25 до 25/1
- botchin
- Поставщик валерьянки для Кота
- Сообщения: 2029
- Зарегистрирован: Чт дек 27, 2012 20:46:09
- Откуда: Болгария, г. Лом
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
Frosty85, посколько тебе нужнъ только состояния с 1/25,6 до 25,6 - в сумме 256 значения, то можно обоитись только считъвание старшего бита ADRESH и лево въравниванием резултата ADFM=0 (теряем 4 младших бита - тъ их так и так потеряеш. Зачем брать их если потом сразу будем делить на 4)
Я в асемблере ето сделал бъ с простъм перемещение десятъчной точкой идникатора.
Я в асемблере ето сделал бъ с простъм перемещение десятъчной точкой идникатора.
Лом - ето город в Болгарии, а не инструмент юстировки електроники.
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
есть формула 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
Я не могу понять в чем проблема?
Оставь пока формулу и обьясни словами что тъ хочешь получить?
Если возмем старшъе 9 битов АЦП (только их) и разделим на 10 то получим как раз етого ряда 0, 0.1, 0.2 ...... 51.1 Если нам нужен обратнъй ряд то инвертируем АЦП
А ~= A; делим на 10 и получаем 51.1, 51.0 .... 0.1,0
Я не понимаю...
Оставь пока формулу и обьясни словами что тъ хочешь получить?
Если возмем старшъе 9 битов АЦП (только их) и разделим на 10 то получим как раз етого ряда 0, 0.1, 0.2 ...... 51.1 Если нам нужен обратнъй ряд то инвертируем АЦП
А ~= A; делим на 10 и получаем 51.1, 51.0 .... 0.1,0
При 9 значущих битах ADC примет значения с 0 до 511Frosty85 писал(а):ADC принимает значения от 51.1 до 1/51.1
Я не понимаю...
Лом - ето город в Болгарии, а не инструмент юстировки електроники.
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
дословно я собираю делитель/множитель частоты. На АЦП я пытаюсь реализовать изменяющийся коэффициент деления/умножения. Т.е. на резисторе относительно среднего положения влево - коэфф. деления, а вправо - коэфф. умножение.
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
Что за дикие числа? Определитесь сколько знаков после запятой необходимо. И необходим ли вообще тип float. Что происходит с данными далее?Frosty85 писал(а):array[1024] = {51.1 , 51, 50.9, 50.8,....,0.019646365, 0.019607843, 0.019569472}
- botchin
- Поставщик валерьянки для Кота
- Сообщения: 2029
- Зарегистрирован: Чт дек 27, 2012 20:46:09
- Откуда: Болгария, г. Лом
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
Вам можеть бъть такой алгоритм:
1. Проверяем старшего бита если он=0 то будем делить
-- инвертируем остальнъе (без старшего)
-- получаем резултат с деления
! 1. старшии бит = 1
-- умножаем
-- получаем результат умножения
Или наоборот (с инвертированием) зависить от реализиции.
1. Проверяем старшего бита если он=0 то будем делить
-- инвертируем остальнъе (без старшего)
-- получаем резултат с деления
! 1. старшии бит = 1
-- умножаем
-- получаем результат умножения
Или наоборот (с инвертированием) зависить от реализиции.
Лом - ето город в Болгарии, а не инструмент юстировки електроники.
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
И? if (adc < 511)Frosty85 писал(а):Т.е. на резисторе относительно среднего положения влево - коэфф. деления, а вправо - коэфф. умножение.
tmp = (tmp*10)/(511-ADC)
иначе
tmp = (tmp*(ADC-512))/10
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
Все я окончательно запутался ))))))
Код: Выделить всё
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
Давайте распутъватся.
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
Попробуй
Остался вопрос про деление на 10. На мой взгляд оно должно бъть после умножение/деление на етого коефициента. Я о том что если разделить коефициента до умножение/деление на 10 то вожножна ситуация когда делим на 0,1 и умножаем на 0,1.
Da-a-a. Здесь вопрос получился .....
Значить у нас три положении: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. Здесь вопрос получился .....
Лом - ето город в Болгарии, а не инструмент юстировки електроники.
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
Спойлер
Код: Выделить всё
#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;
}
}
}
}
/****************************************************************/
В исходном варианте был просто #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
Я заменил float k на unsigned int k.
.
Здесь другая проблема возникает. Диапазон ADC 512 +/- 10. Етот диапазон каким-то образом нужно свести к нормалной стойности. А то получается делим и получаем больше (к=0.1)
.
Здесь другая проблема возникает. Диапазон ADC 512 +/- 10. Етот диапазон каким-то образом нужно свести к нормалной стойности. А то получается делим и получаем больше (к=0.1)
Лом - ето город в Болгарии, а не инструмент юстировки електроники.
Re: АЦП pic12f629 вопрос по регистрам ADRESL и ADREHL
Код: Выделить всё
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
Заметь что я переправил код что дал
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
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 раз.
Лом - ето город в Болгарии, а не инструмент юстировки електроники.


