Help in A/D

Discussion in 'Embedded Systems and Microcontrollers' started by moahrs, Dec 9, 2011.

  1. moahrs

    Thread Starter New Member

    Dec 5, 2011
    8
    0
    Hi all,

    I have the program below, i have trying to use the AD in 18F2550. I searched many samples and tips, but not work.

    My idea is read position in a touch screen. The circuit (hardware) is ok, tested. The voltage is changing correctly, but the 18F2550 dont convert to digital.

    How work:
    - CPU (Z80) generate INT to INT2 in 18f2550, and send the byte 0x01 which indicates to read the touch;
    - 18f2550 go to read touch. First I configure all necessary, OUT_TFFT indicate what was read (x- or y-), in this case, 18f2550 only leave the loop if read anything in x- first;
    - When AD finish, it generate a interrupt low priority, and verify if any was read, if "0x00", it generate a delay and start new conversion (in interruption yet).
    - If was read a valid number (padlido <> 0x00), the system go to next positon (y-) and do same operations;
    - When was read a valid number in x- and y-, he compare if is equal to previous ppox and ppoxy, if is, start all process again, until read a valid number;
    - if valid number is read an diferente from previous, he generate a interrupt in cpu Z80, and wait cpu returna to get the positons.

    My problem is that the 18f2550 is not reading any valor correct, he is only reading the same valor, 0x00, and not leave from process.

    Ty for help.

    below, my code:
    Code ( (Unknown Language)):
    1.  
    2. #include <pic18f2550.h>
    3.  
    4. static __code char __at(__CONFIG1H) conf1H = _OSC_INTOSC__USB_HS_1H;
    5. //static __code char __at(__CONFIG1L) conf1L = _PLLDIV_DIVIDE_BY_5__20MHZ_INPUT__1L & _CPUDIV__OSC1_OSC2_SRC___1__96MHZ_PLL_SRC___2__1L;
    6. static __code char __at(__CONFIG2H) conf2H = _WDT_DISABLED_CONTROLLED_2H;
    7. static __code char __at(__CONFIG3H) conf3H = _MCLRE_MCLR_OFF_RE3_ON_3H;
    8. static __code char __at(__CONFIG4L) conf4 = _LVP_OFF_4L & _ENHCPU_OFF_4L; // & _BACKBUG_OFF_4L & _STVR_OFF_4L;
    9.  
    10. #define OUT_TFFT LATAbits.LATA2
    11. #define OUT_CTRLWAIT LATAbits.LATA4
    12. #define OUT_INTZ80 LATAbits.LATA5
    13.  
    14. #define OUT_CPU0 LATCbits.LATC0
    15. #define OUT_CPU1 LATCbits.LATC1
    16. #define OUT_CPU2 LATCbits.LATC2
    17. #define OUT_CPU3 LATBbits.LATB3
    18. #define OUT_CPU4 LATBbits.LATB4
    19. #define OUT_CPU5 LATBbits.LATB5
    20. #define OUT_CPU6 LATBbits.LATB6
    21. #define OUT_CPU7 LATBbits.LATB7
    22.  
    23. #define IN_CPU0 PORTCbits.RC0
    24. #define IN_CPU1 PORTCbits.RC1
    25. #define IN_CPU2 PORTCbits.RC2
    26. #define IN_CPU3 PORTBbits.RB3
    27. #define IN_CPU4 PORTBbits.RB4
    28. #define IN_CPU5 PORTBbits.RB5
    29. #define IN_CPU6 PORTBbits.RB6
    30. #define IN_CPU7 PORTBbits.RB7
    31.  
    32. #define IN_PC5 PORTEbits.RE3    
    33. #define IN_PC6 PORTAbits.RA3
    34. //#define IN_CS2 PORTBbits.RB2
    35.  
    36. // PC6 | PC5 | Result
    37. //  0  |  0  | Ok
    38. //  0  |  1  | WR Data Z80 -> PIC
    39. //  1  |  0  | RD Data PIC -> Z80
    40. //  1  |  1  | RD CTRL PIC -> Z80
    41.  
    42. //#define debug 1
    43.  
    44. volatile unsigned char pbyte;
    45. volatile unsigned char pbytectrl;
    46. volatile unsigned char pposx;
    47. volatile unsigned char pposy;
    48. volatile unsigned char padlido;
    49. volatile unsigned char pbyteler[64];
    50. volatile unsigned char ploop;
    51.  
    52. void EnviaByte();
    53. unsigned char RecebeByte();
    54. void ProcessaAD();
    55. void ProcessaUSB();
    56. void LerTouch();
    57. void ComunicarUSB();
    58. void ComunicarSerial();
    59.  
    60. void main()
    61. {
    62.     // CONFIGURAR PORTAS
    63.     OSCCON = 0x70;
    64.     ADCON1 = 0x0D;    // RA0=AN0, RA1=AN1, TODAS AS DEMAIS ANx = DIGITAIS
    65.     PORTA = 0x30;
    66.     PORTB = 0x00;
    67.     PORTC = 0x00;
    68.     TRISA = 0x0B;    // RA7-X, RA6-X, RA5-INTZ80, RA4-CTRWAIT, RA3-PC6, RA2-X+/Y+, RA1-AN1, RA0-AN0
    69.     TRISB = 0xFC;    // RB7 A RB3 - D7 A D3, RB2-INT2/CS2, RB1-SCL, RB0-SCA
    70.     TRISC = 0x97;    // RC7-RX, RC6-TX, RC5-D+, DC4-D-, RC3-X, RC2 A RC0 - D2 A D0, RE3-PC5
    71.  
    72.     RCON = RCON | 0x80;
    73.     PIR1 = 0x00;
    74.     PIR2 = 0x00;
    75.     PIE1 = 0x00;
    76.     PIE2 = 0x00;
    77.     IPR1 = 0x00;
    78.     IPR2 = 0x00;
    79.     INTCON = 0xC0;    // 0xC0
    80.     INTCON2 = 0xE0;   // 0xE0
    81.     INTCON3 = 0x90;   // 0x90
    82.  
    83.     ADCON2bits.ADFM = 0x01;    // right justied
    84.     ADCON2bits.ACQT2 = 0x00;
    85.     ADCON2bits.ACQT1 = 0x00;
    86.     ADCON2bits.ACQT0 = 0x00; // 0 TAD
    87.     ADCON2bits.ADCS2 = 0x01;
    88.     ADCON2bits.ADCS1 = 0x01;
    89.     ADCON2bits.ADCS0 = 0x01; // FRC
    90.     ADCON0bits.ADON = 0x01;  // ADC ON
    91.  
    92.     pbyte = 0x00;
    93.     pbytectrl = 0x00;
    94.     OUT_TFFT = 0;
    95.  
    96.     INTCON3bits.INT2IE = 0x01;
    97.     PIE1bits.ADIE = 0x01;
    98.  
    99.     while(1)
    100.     {
    101.         switch (pbyte)
    102.         {
    103.             case 0x01:
    104.                 LerTouch();
    105.                 break;
    106.             case 0x02:
    107.                 ComunicarUSB();
    108.                 break;
    109.             case 0x03:
    110.                 ComunicarSerial();
    111.                 break;
    112.         }
    113.     }
    114. }
    115.  
    116. void isr_reset(void) __interrupt 0
    117. {
    118.     INTCON3bits.INT2IE = 0x00;
    119.     PIE1bits.ADIE = 0x00;
    120.     INTCON3bits.INT2IF = 0x00;
    121.     PIR1bits.ADIF = 0x00;
    122.     PIR2bits.USBIF = 0x00;
    123.  
    124.     main();
    125. }
    126.  
    127. void isr_int2(void) __interrupt 1
    128. {
    129.     // DESLIGA INTERRUPCAO PARA EVITAR NOVAS SOLICITACOES
    130.     OUT_INTZ80 = 0x01;
    131.     INTCON3bits.INT2IE = 0x00;
    132.     PIE1bits.ADIE = 0x00;
    133.    
    134.     if (INTCON3bits.INT2IF == 0x01)    // INTERRUPCAO SOLICITADA PELO Z80
    135.     {
    136.         // DESLIGA FLAG DE INT2
    137.         INTCON3bits.INT2IF = 0x00;
    138.  
    139. #ifndef debug
    140.         if (IN_PC6 == 0 && IN_PC5 == 1)              // WR DADOS
    141.             pbyte = RecebeByte();
    142.         if (IN_PC6 == 1 && IN_PC5 == 0)              // RD DADOS
    143.             EnviaByte;
    144.         if (IN_PC6 == 1 && IN_PC5 == 1)              // RD CTRL
    145.             EnviaByte;
    146. #endif
    147.     }
    148.  
    149.     // LIGA INTERRUPCAO
    150.     INTCON3bits.INT2IE = 0x01;
    151.     PIE1bits.ADIE = 0x01;
    152. }
    153.  
    154. void isr_AD_USB(void) __interrupt 2
    155. {
    156.     // DESLIGA INTERRUPCOES PARA EVITAR NOVAS SOLICITACOES
    157.     PIE1bits.ADIE = 0x00;
    158.  
    159.     if (PIR1bits.ADIF == 0x01) // INTERRUPCAO SOLICITADA PELO CANAL DE A/D
    160.     {
    161.         PIR1bits.ADIF = 0x00;
    162.         ProcessaAD();
    163.     }
    164.     else if (PIR2bits.USBIF == 0x01) // INTERRUPCAO SOLICITADA PELO CANAL USB
    165.     {
    166.         PIR2bits.USBIF = 0x00;
    167.         ProcessaUSB();
    168.     }
    169.  
    170.     // LIGA INTERRUPCOES
    171.     PIE1bits.ADIE = 0x01;
    172. }
    173.  
    174. void EnviaByte()
    175. {
    176.     unsigned char oldTRISB, oldTRISC, vbyte;
    177.  
    178.     // SALVA VALORES ATUAIS DO STATUS DAS PORTAS
    179.     oldTRISB = TRISB;
    180.     oldTRISC = TRISC;
    181.  
    182.     // DEFINE NOVOS VALORES
    183.     TRISB = 0x04;
    184.     TRISC = 0x90;
    185.     vbyte = 0x00;
    186.  
    187.     if (IN_PC6 == 1 && IN_PC5 == 0)        // RD DADOS
    188.         vbyte = pbyteler[ploop];
    189.     else if (IN_PC6 == 1 && IN_PC5 == 1)        // RD CTRL
    190.         vbyte = pbytectrl;
    191.  
    192.     if (pbytectrl != 0x00)
    193.     {
    194.         ploop++;
    195.         if (ploop >= (pbytectrl & 0x3F))
    196.             pbytectrl = 0x00;
    197.     }
    198.  
    199.     // ENVIA BYTE PELA PORTA
    200.     OUT_CPU0 = vbyte & 0x01;
    201.     vbyte = vbyte >> 1;
    202.     OUT_CPU1 = vbyte & 0x01;
    203.     vbyte = vbyte >> 1;
    204.     OUT_CPU2 = vbyte & 0x01;
    205.     vbyte = vbyte >> 1;
    206.     OUT_CPU3 = vbyte & 0x01;
    207.     vbyte = vbyte >> 1;
    208.     OUT_CPU4 = vbyte & 0x01;
    209.     vbyte = vbyte >> 1;
    210.     OUT_CPU5 = vbyte & 0x01;
    211.     vbyte = vbyte >> 1;
    212.     OUT_CPU6 = vbyte & 0x01;
    213.     vbyte = vbyte >> 1;
    214.     OUT_CPU7 = vbyte & 0x01;
    215.  
    216.     // RETIRA Z80 DO WAIT
    217.     OUT_CTRLWAIT = 0x00;
    218.  
    219.     // AGUARDA ATE A CPU SAIR DA LEITURA
    220.     while (IN_PC6 != 0x00 || IN_PC5 != 0x00);
    221.  
    222.     // RECOLOCA SINAL WAIT PARA PROXIMO ACESSO Z80
    223.     OUT_CTRLWAIT = 0x01;
    224.  
    225.     // VOLTA VALORES ATUAIS DAS PORTAS
    226.     PORTB = 0x00;
    227.     PORTC = 0x00;
    228.     TRISB = oldTRISB;
    229.     TRISC = oldTRISC;
    230. }
    231.  
    232. unsigned char RecebeByte()
    233. {
    234.     unsigned char oldTRISB, oldTRISC;
    235.     unsigned int vbyte, vbyte1;
    236.  
    237.     // SALVA VALORES ATUAIS DO STATUS DAS PORTAS
    238.     oldTRISB = TRISB;
    239.     oldTRISC = TRISC;
    240.  
    241.     // DEFINE NOVOS VALORES
    242.     TRISB = 0xFC;
    243.     TRISC = 0x97;
    244.  
    245.     // RECEBER VALOR PELAS 2 PORTAS
    246.     vbyte = PORTB & 0xF8;
    247.     vbyte1 = PORTC & 0x07;
    248.     vbyte = vbyte + vbyte1;
    249.  
    250.     // RETIRA Z80 DO WAIT
    251.     OUT_CTRLWAIT = 0x00;
    252.  
    253.     // AGUARDA ATE A CPU SAIR DA GRAVAÇÃO
    254.     while (IN_PC6 != 0x00 || IN_PC5 != 0x00);
    255.  
    256.     // RECOLOCA SINAL WAIT PARA PROXIMO ACESSO Z80
    257.     OUT_CTRLWAIT = 0x01;
    258.  
    259.     // VOLTA VALORES ATUAIS DAS PORTAS
    260.     PORTB = 0x00;
    261.     PORTC = 0x00;
    262.     TRISB = oldTRISB;
    263.     TRISC = oldTRISC;
    264.  
    265.     return vbyte;
    266. }
    267.  
    268. void ProcessaAD()
    269. {
    270.     unsigned int cc;
    271.  
    272.     padlido = ADRESL;
    273.     padlido += (ADRESH << 6);
    274.  
    275.     if (padlido == 0x00)
    276.     {
    277.         for (cc = 0; cc <= 0x1FF; cc++);
    278.  
    279.         ADCON0bits.GO = 0x01;
    280.     }
    281. }
    282.  
    283. void ProcessaUSB()
    284. {
    285.     pbytectrl = 0x20;    // Indica USB (0b10) e 1 byte de informacao (0b000000) (valor + 1)
    286. }
    287.  
    288. void LerTouch()
    289. {
    290.     unsigned char vloop;
    291.     unsigned char pposantx, pposanty;
    292.     unsigned int cc;
    293.  
    294.     pbyte = 0x00;
    295.     vloop = 0x01;
    296.     pposantx = 0x00;
    297.     pposanty = 0x00;
    298.     pposantx = pposx;
    299.     pposanty = pposy;
    300.  
    301.     OUT_TFFT = 0x01;
    302.     ADCON0bits.CHS0 = 0x00;
    303.     ADCON0bits.CHS1 = 0x00;
    304.     ADCON0bits.CHS2 = 0x00;
    305.     ADCON0bits.CHS3 = 0x00;
    306.  
    307.     // Primeiro Espera Um Touch no LCD pelo Canal X+
    308.     while (vloop == 0x01)
    309.     {
    310.         // Inicia Conversao
    311.         padlido = 0x00;
    312.         PIR1bits.ADIF = 0x00;
    313.         for (cc = 0; cc <= 0x0FF; cc++);
    314.         ADCON0bits.GO = 0x01;
    315.        
    316.         // Aguarda a Interrupção do AD com o Valor
    317.         while (padlido == 0x00);
    318.  
    319.         if (OUT_TFFT == 0x01)
    320.         {
    321.             pposx = padlido;
    322.  
    323.             // MUDA PARA O CANAL Y+
    324.             OUT_TFFT = 0x00;
    325.             ADCON0bits.CHS0 = 0x01;
    326.         }
    327.         else
    328.         {
    329.             pposy = padlido;
    330.  
    331.             if (pposx != pposantx || pposy != pposanty)
    332.                 vloop = 0x00;
    333.         }
    334.     }
    335.  
    336.     // Finaliza, envia bytes pro Z80
    337.     pbyteler[0] = pposx;
    338.     pbyteler[1] = pposy;
    339.     ploop = 0x00;
    340.     pbytectrl = 0x41;    // Indica AD (0b01) e 2 bytes de informacao (0b000001) (valor + 1)
    341.  
    342.     OUT_INTZ80 = 0x00;
    343. }
    344.  
    345. void ComunicarUSB()
    346. {
    347.     pbyte = 0x00;
    348. }
    349.  
    350. void ComunicarSerial()
    351. {
    352.     pbyte = 0x00;
    353. }
    354.  
    355.  
     
    Last edited by a moderator: Dec 9, 2011
  2. DerStrom8

    Well-Known Member

    Feb 20, 2011
    2,428
    1,328
    Which compiler is this? Hi-Tech?

    Anyway, I recently learned how to use the ADC on the 18F1330 and I have a few questions for you. First, I'm not sure about this, but I think

    ADCON2bits.ACQT0 = 0x00; // 0 TAD

    is saying you're not giving the ADC any time to acquire a value. Setting it to, say, 20 TAD might work better. Second, I don't see where you wait for the ADC to finish the conversion--you just skip ahead to the next piece of code. You need to have a line that says something like while(BusyADC()); or something like that. I think there's actually a bit for that, so you might be able to use that rather than the library function BusyADC. And lastly, I don't see where you read the ADC. Again, you can use the ReadADC() library function or find the bit that says to read the value.
    If there's something I missed, please point it out to me. I hope you can figure it out soon!
    Regards,
    Der Strom
     
    moahrs likes this.
  3. moahrs

    Thread Starter New Member

    Dec 5, 2011
    8
    0
    First of all, thank you for explanations.

    I Using SDCC. I can't use HI_TECH and MPLAB, and how my patience is very short, and dont work anytime, i decided to use SDCC and work very well..

    I was put 20 TAD, but the same, don't work. I decided use the control of TAD with for(cc=0;cc<=0x00FF;cc++). I wait finish the conversion with while(padlido==0x00), and finish with interrupt.
     
  4. DerStrom8

    Well-Known Member

    Feb 20, 2011
    2,428
    1,328
    May I ask why you can't use MPLAB and Hi-Tech?
     
    moahrs likes this.
  5. moahrs

    Thread Starter New Member

    Dec 5, 2011
    8
    0
    See, i try compile em MPASM, same program compile in anyone ASM compiler, but in MPASM not.

    I Try HI-TECH C, I had setup, how write in site and instructions, but the MPLAB dont find it... Only says that dont cant use HI-TECH because cant find it... but the directory is OK...

    I think that its me the problem, but how I use SDCC at long time ago for Z80, 8051 and other, I decided to use in PIC18. Until now, its working OK... "Only this problem with AD"...

    But if you think that I need try, "again", install HI-TECH and use him, i can try, and tomorow post here the result.

    More one time, ty...
     
  6. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    On my computers I have no problem with MPLAB not finding HI-Tech C. Have you read the quickstart.pdf in the docs folder. The path is something like this
    C:\Program Files\HI-TECH Software\PICC-18\PRO\9.64\docs
     
    moahrs likes this.
  7. moahrs

    Thread Starter New Member

    Dec 5, 2011
    8
    0
    Hum... I understand. I will try again. But, in the my code, have anyone problem that need I to fix ?

    I will thinking in change interrupt for loop seeing if ADCON0.GO is in "0".

    What u think ?
     
  8. DerStrom8

    Well-Known Member

    Feb 20, 2011
    2,428
    1,328
    Do you go through the project wizard in MPLAB? It makes things a LOT easier. When you open it up, go to Project-->Project Wizard. It will walk you through the proper setup process, including finding the correct location for Hi-Tech. Another idea, if you are using an 18F processor, is C18 lite, which is the compiler I use. You can download it for free from the Microchip website.
     
  9. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    I agree with always starting from the Project Wizard.

    To just inform MPLAB where a tool is (such as a compiler) you can use "Set Language Tool Locations..." under the Project menu.
     
  10. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    This part:

    Code ( (Unknown Language)):
    1.  
    2. void ProcessaAD()
    3. {    
    4. unsigned int cc;    
    5.  padlido = ADRESL;    
    6. padlido += (ADRESH << 6);    
    7.  if (padlido == 0x00)    
    8. {        
    9. for (cc = 0; cc <= 0x1FF; cc++);          
    10. ADCON0bits.GO = 0x01;    
    11. }
    12. }
    13.  
    After ADCON0bits.GO=0x01;

    In addition to giving more time for the ADC to complete (20 TAD is good)

    Add a line:
    While (ADCON0bits.go);

    I'm unsure why you have it in a for loop, since you are continually restarting the AD conversion each time?

    That will keep the function from returning from the subroutine before the AD conversion is complete.

    Maybe put the move from ADRES to after the while(ADCON0.go) as well, so the function will return a result.
     
  11. nigelwright7557

    Senior Member

    May 10, 2008
    487
    71
    ;here is my code tha tworks.
    ADCON1=0Xd;
    ADCON0=1;
    ADCON2=0XB6;
    ADCON0bits.GO_DONE=1; //START A2D first time
    reloop:
    if (ADCON0bits.GO_DONE==1)
    goto reloop;

    //result to data
    data=ADRESL+256*ADRESH;
     
  12. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    So does that cover all of your problems, or is something else not working?
     
Loading...