|
Виж темите без отговор | Виж активните теми
Дата и час: Вто Юли 28, 2026 7:11 am
|
Страница 1 от 1
|
[ 6 мнения ] |
|
Проблем при АЦП на ПИК16Ф887.
| Автор |
Съобщение |
|
misho
Ранг: Минаващ
Регистриран на: Пон Авг 24, 2009 7:48 pm Мнения: 15
|
 Проблем при АЦП на ПИК16Ф887.
Привет,
Искам чрез потенциометър свързан между Vdd, Vss и RA0 да измервам входното напрежение, след това да го изведа на PC през RS232, като измерване да се прави при всяко препълване на таймера. За опорни напрежения ползвам Vdd и Vss. Проблемът е, че от АЦП-то получавам безмислици. Използвам CCS компилатор в MPLAB среда. Приложил съм кода.
#include <16F887.h>
#include <stdlib.h>
#use fast_io(A)
#use fast_io(C)
#use delay(clock=4000000)
#use rs232(baud = 9600, xmit = PIN_C6, rcv = PIN_C7)
#FUSES INTRC,NOWDT,NOPUT,NOMCLR,NOPROTECT,NOCPD,NOBROWNOUT,NOIESO,NOFCMEN,NOLVP
#byte ADCON1 = 0x9F
unsigned int adc_conversion = 0;
int flag;
void init_io()
{
SET_TRIS_A(0x01);
OUTPUT_B(0x00);
SET_TRIS_C(0x80);
OUTPUT_D(0x00);
OUTPUT_E(0x00);
}
void init_adc()
{
SETUP_ADC_PORTS(sAN0 | VSS_VDD);
SETUP_ADC(ADC_CLOCK_DIV_8);
SET_ADC_CHANNEL(0);
READ_ADC(ADC_START_ONLY);
}
#INT_RTCC
void timer0_interrupt_service()
{
adc_conversion = READ_ADC(ADC_READ_ONLY);
flag = 1;
READ_ADC(ADC_START_ONLY);
}
void main()
{
char mV[20];
unsigned long value = 0;
flag = 0;
init_io();
setup_uart(9600);
init_adc();
ADCON1 = 0x80;
SETUP_TIMER_0(RTCC_INTERNAL | RTCC_DIV_256);
ENABLE_INTERRUPTS(GLOBAL);
ENABLE_INTERRUPTS(INT_RTCC);
while(1)
{
if (flag == 1)
{
flag = 0;
value = adc_conversion*5000/1024;
itoa(value,10,mV);
puts(mV);
putc(0x0D);
}
}
}
|
| Пон Авг 24, 2009 8:05 pm |
|
 |
|
ToHu
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 9:21 pm Мнения: 30686 Местоположение: София
|
ммм малко разхвърляно ми седи ето как става :
тва ти е в хедър
#include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
тва ти е кода, реално кода който имаш да напишеш е буквално 5 реда
#include "C:\MyDocuments\Isdelia\test\877.h"
#bit start = 0x1F.2
int1 AD_OK; int result;
#int_RTCC
RTCC_isr()
{
start = 1;
}
#int_AD
AD_isr()
{
AD_OK=true; result = read_adc(adc_read_only);
}
void main()
{
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_32);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);
enable_interrupts(INT_AD);
enable_interrupts(GLOBAL);
AD_OK=false;
while(true) { if(AD_OK) { AD_OK=false; printf("%d \r\n", result); }
}
}
|
| Пон Авг 24, 2009 8:41 pm |
|
 |
|
ToHu
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 9:21 pm Мнения: 30686 Местоположение: София
|
Ама така като ти гледам кода май нещо не ти е съвсем ясно. Гледам че в прекъсването от таймера първо четеш ADC а след това го пускаш, това не е правилно, ти не можеш да знаеш дали е приключило конвертирането когато влизаш в това прекъсване, освен ако не е достатъчно дълго времеро за запълване на тоя таймер. Ако ще четеш така би трябвало да проверяваш първо дали е свършило.
После с това конвертиране което правиш ..... много омотано, имаш printf функция. И не на последно място в CCS израз от сорта result*5000/1024 не е сигурно какъв резултат ще даде ....
п.с. всъщност умношено по 5000 е нормално да връща глупости, явно си РС програмист, int e 8 битово, и освен това по този начин трябва да декларираш много голяма променлива, тъй като и 16 битово ще се препълни при 1024*5000, кеото ще е факт при 5 В на входа....
иии последно, по тоя начин не можеш да мериш захранващото напрежение, тъй като то ти е и опорно, за да мериш захранващото трябва да имаш ИОН
|
| Пон Авг 24, 2009 8:54 pm |
|
 |
|
RM
Ранг: Почетен член
Регистриран на: Нед Окт 19, 2008 7:26 pm Мнения: 673
|
Така става по добре, но да използва поне стабилно външно Vref
Почва да ме хваща яд на CCS и на PIC .....  кат чели не са толко черни 
_________________ Вниманиене съмвишист....ИЙ.
|
| Пон Авг 24, 2009 10:19 pm |
|
 |
|
misho
Ранг: Минаващ
Регистриран на: Пон Авг 24, 2009 7:48 pm Мнения: 15
|
Благодаря за отговорите. Както сте разбрали съм начинаещ и имам много да уча. Като се снабдя с външно Vref ще пробвам пак.
|
| Пон Авг 24, 2009 11:14 pm |
|
 |
|
ToHu
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 9:21 pm Мнения: 30686 Местоположение: София
|
RM.... абе може и да не се пише толкова сложно, CCS в това отношение е малко умен да му се невиди, може да си декларираш int16 или каквото там искаш и да четеш с read_adc() директно 10 битова стойност, но трябва да си казал на компилатора че ще ползваш 10 битово ADC, при менима директива че ще е 8 битово. По принцип за да има стабилно отчитане е хубаво да се осреднят няколко отчета, т.е. това което съм написал ще стане нещо от сорта :
#int_AD
AD_isr()
{
temp+=read_adc(adc_read_only); // тук се натрупват няколко отчета в променлива temp
count++;
if(count>3) // те тук си правиш проверка колко отчета си направил
{
count=0;
AD_OK=true;
result = temp>>2; // дели се на 4, тъй като натрупвам 4 отчета, т.е. средно аритметично
temp=0;
}
така имаш усреднение от 4 отчета, това разбира се може да се напише по различни начини, показвам принципа а не стил на писане, въпреки че аз предпочитам да е точно така вместо четенето да е в else на IF-а.
После преобразуването в mV най добре да стане с нещо от сорта :
(result*39)>>3, това ако работи с 16 битово число, 39 ~ 5000*8/1024 , не е само 5000 / 1024 за да се запази точността. Ако работи с 32 битово число вече може да е още по точно, трябва да прецени колко му трябва, като това всъщност зависи не само от това с каква точност смята а и от разредноста на ADC-то, от неговата грешка и от точноста на опорното напрежение.
п.с. относно CCS е перфектен за процесорчето за кеото е създаден, от друга страна пък това процесорче е перфектно за някои нужди, така че си имат своето местенце ..... на мен силабс ми допадат, обаче колкот и да си кривя душата няма начин да напишеш толкова проста програмка за толквоа кратко време, докато инициализираш серийния, докато се сетиш кои бяха регистрите, щото там не мога фи запомня на изсут и тва си е ... та си има предимства, просто процесорче за прости неща ...
|
| Вто Авг 25, 2009 11:46 am |
|
|
|
Страница 1 от 1
|
[ 6 мнения ] |
|
Кой е на линия |
Потребители разглеждащи този форум: 0 регистрирани и 2 госта |
|
Вие не можете да пускате нови теми Вие не можете да отговаряте на теми Вие не можете да променяте собственото си мнение Вие не можете да изтривате собствените си мнения Вие не можете да прикачвате файл
|
|