PIC10F322 AD Project in Assembly, RS232

(instructions, reset, WDT, specifications...) PIC10F2xx, PIC12F5xx, PIC16F5x

PIC10F322 AD Project in Assembly, RS232

Postby Tom Maier » Mon May 26, 2014 4:00 pm

deleted
Last edited by Tom Maier on Thu Sep 11, 2014 1:33 pm, edited 1 time in total.
User avatar
Tom Maier
Verified identity
 
Posts: 179
Joined: Mon May 26, 2014 2:37 pm
PIC experience: Professional 5+ years with MCHP products

Re: PIC10F322 AD Project in Assembly, RS232

Postby Tom Maier » Mon May 26, 2014 4:06 pm

deleted
Last edited by Tom Maier on Thu Sep 11, 2014 1:36 pm, edited 2 times in total.
User avatar
Tom Maier
Verified identity
 
Posts: 179
Joined: Mon May 26, 2014 2:37 pm
PIC experience: Professional 5+ years with MCHP products

Re: PIC10F322 AD Project in Assembly, RS232

Postby Tom Maier » Mon May 26, 2014 4:13 pm

deleted
Last edited by Tom Maier on Thu Sep 11, 2014 1:37 pm, edited 1 time in total.
User avatar
Tom Maier
Verified identity
 
Posts: 179
Joined: Mon May 26, 2014 2:37 pm
PIC experience: Professional 5+ years with MCHP products

Re: PIC10F322 AD Project in Assembly, RS232

Postby Tom Maier » Mon May 26, 2014 4:15 pm

Hey... that worked.
User avatar
Tom Maier
Verified identity
 
Posts: 179
Joined: Mon May 26, 2014 2:37 pm
PIC experience: Professional 5+ years with MCHP products

Re: PIC10F322 AD Project in Assembly, RS232

Postby robA » Mon May 26, 2014 5:52 pm

My experience with other pics is that you could easily change the A>D input resistor values to be 1M0 and 200k without losing accuracy because you have the 100nF input caps.
robA
 
Posts: 1
Joined: Mon May 26, 2014 5:48 pm
PIC experience: Professional 5+ years with MCHP products

Re: PIC10F322 AD Project in Assembly, RS232

Postby Tom Maier » Mon May 26, 2014 6:04 pm

I picked the 10K because it allows a bandwidth of greater then 60 Hz when using the 0.1 uF cap. People can use whatever they want, this was just a test of the part and my new pickit 3, which I had just bought back then.

The two things to watch out for with the very high resistors is that the internal ad frontend may have leakage and there also might be schmutz on the board that creates an external leakage path. That leads to errors. I always try to go as low with that input impedance as much as I can.
User avatar
Tom Maier
Verified identity
 
Posts: 179
Joined: Mon May 26, 2014 2:37 pm
PIC experience: Professional 5+ years with MCHP products

Re: PIC10F322 AD Project in Assembly, RS232

Postby MMcLaren » Mon Sep 01, 2014 2:29 pm

The bit to bit timing in Tom's serial routine seems to be ~109 cycles instead of the 104 cycles he intended which results in a bit rate error of about 4.5% (± 1% for INTOSC). That means the routine could be as much as 35 cycles (33%) late sending the 8th data bit. Tweaking the serial routine to produce precise 104 cycle bit timing should produce a bit rate error of about 0.16% (±1%).

I couldn't resist writing an untested variation of Tom's fine demo. It uses a "cycle accurate" fixed delay subsystem to provide precise timing for 38400 baud and approximately 1000 samples per second (AN0 and AN1) with an Fosc of 4, 8, or 16-MHz.

Cheerful regards, Mike

Code: Select all
;******************************************************************
;                                                                 *
;   Filename: 10F322 Serial ADC Demo.asm                          *
;     Author: Mike McLaren, K8LH                                  *
;       Date: 31-Aug-2014                                         *
;                                                                 *
;   Read and send 8-bit ADC(0) and ADC(1) results via serial on   *
;   the RA2 pin (38400 baud).                                     *
;                                                                 *
;      MPLab: 8.92    (tabs = 8)                                  *
;      MPAsm: 5.51                                                *
;                                                                 *
;******************************************************************

        list p=10f322, st=off
        #include "p10f322.inc"
        radix dec

        __CONFIG _FOSC_INTOSC & _WDTE_OFF & _MCLRE_OFF & _LVP_OFF


;--< variables >---------------------------------------------------

        cblock 0x40             ; start of 10F322 RAM (0x40..0x7F)
txbyte                          ; put232() subroutine
bitctr                          ; put232() subroutine
        endc

;--< constants >---------------------------------------------------

TxPin   equ     RA2             ;


;==================================================================
;  K8LH delayCy() subsystem macro generates two instructions
;
clock   equ     4               ; 4, 8, 12, or 16 MHz clock
usecs   equ     clock/4         ; cycles/usec operand multiplier

delayCy macro   delay           ; range 8..1031 (cycles)
        movlw   (delay-8)/4+1
        call    iDelay-(delay%4)
        endm

;==================================================================
;  readADC() macro
;
ReadADC macro   channel         ; 0, 1, or 2
        movlw   channel<<CHS0   ; shift into correct position     |00
;       xorwf   ADCON,W         ; delta CHS<2:0> old and new      |00
;       andlw   b'00011100'     ; filter out non CHS<2:0> bits    |00
;       xorwf   ADCON,F         ; set new CHS<2:0> 'chan' bits    |00
        call    getADC          ;                                 |00
        endm                    ;

;******************************************************************
;  reset vector                                                   *
;******************************************************************
        org     0x000
v_reset
        goto    init            ;                                 |00

;******************************************************************
;  interrupt vector                                               *
;******************************************************************
        org     0x004
v_int

;******************************************************************
;  main init                                                      *
;******************************************************************

init
;       movlw   b'01110000'     ; value for 16-MHz                |00
;       movlw   b'01100000'     ; value for 8-MHz                 |00
        movlw   b'01010000'     ; value for 4-MHz                 |00
        movwf   OSCCON          ; change INTOSC speed             |00
        delayCy(250*usecs)      ;                                 |00
;
;  setup PORTA digital and ADC pins
;
        movlw   1<<RA0|1<<RA1   ; RA0, RA1 (and RA3) inputs       |00
        movwf   TRISA           ; RA2 (TxPin) is an output        |00
        bsf     PORTA,TxPin     ; set TxPin (RA2) high            |00
        movlw   1<<ANSA0|1<<ANSA1
        movwf   ANSELA          ; RA0/RA1 (ch 0/1) ADC 'on'       |00
;
;  setup ADC clock source to OSC/16 (leave ADC 'off')
;
        bsf     ADCON,ADCS2     ; ADC conversion clock OSC/16     |00
        bcf     ADCON,ADCS1     ;  "                              |00
        bsf     ADCON,ADCS0     ;  "                              |00

;******************************************************************
;  main loop  (approximately 1000 AN0 + AN1 samples per second)   *
;******************************************************************

main
        ReadADC(0)              ; read ADC channel 0 (RA0)        |00
        call    put232          ; send raw 8-bit ADC result in W  |00
        delayCy(50*usecs)       ; 50-usec inter-char delay        |00

        ReadADC(1)              ; read ADC channel 1 (RA1)        |00
        call    put232          ; send raw 8-bit ADC result in W  |00
        delayCy(50*usecs)       ; 50-usec inter-char delay        |00

        movlw   '\r'            ; use <cr> character (0x0D)       |00
        call    put232          ; as line terminator char         |00
        delayCy(50*usecs)       ; 50-usec inter-char delay        |00

        goto    main            ; loop forever                    |00

;******************************************************************
;  getADC(), pass channel number, 0-2 (shifted left two bits) in  *
;  wreg on entry and pass the 8-bit ADC result in wreg on exit.   *
;                                                                 *
getADC                          ;**********************************
        xorwf   ADCON,W         ; setup new CHS (channel) bits    |00
        andlw   b'111'<<CHS0    ; filter out non CHS<2:0> BITS    |00
        xorwf   ADCON,F         ; set new CHS<2:0> ADC channel    |00
        bsf     ADCON,ADON      ; turn ADC 'on'                   |00
        delayCy(10*usecs)       ; 10-usec acquisition delay       |00
        bsf   ADCON,GO_NOT_DONE ; start conversion                |00
adcrdy
        btfsc ADCON,GO_NOT_DONE ; done? yes, skip, else           |00
        goto    adcrdy          ; wait for conversion complete    |00
        movf    ADRES,W         ; wreg = 8-bit ADC result         |00
        bcf     ADCON,ADON      ; turn ADC 'off'                  |00
        return                  ;                                 |00

;******************************************************************
;  put232 subroutine (change 'skpc' to 'skpnc' to rev polarity).  *
;                                                                 *
;  delayCy(104*usecs-10) -> 9600 (0.16%) (4, 8, or 16-MHz clock)  *
;  delayCy(52*usecs-10) -> 19200 (0.16%) (4, 8, or 16-MHz clock)  *
;  delayCy(26*usecs-10) -> 38400 (0.16%) (4, 8, or 16-MHz clock)  *
;                                                                 *
put232                          ;**********************************
        movwf   txbyte          ; save Tx data                    |00
        movlw   11              ; 1 start + 8 data + 1 stop bit   |00
        movwf   bitctr          ; setup bit counter               |00
        clrc                    ;                                 |00
        goto    sendbit         ;                                 |00
nextbit
        delayCy(26*usecs-10)    ; 52-usecs -10 cycle loop time    |00
        setc                    ; always shift in a 'stop' bit    |00
        rrf     txbyte,F        ; put data bit in Carry           |00
sendbit
        movf    PORTA,W         ; read port                       |00
        iorlw   1<<TxPin        ; set TxPin bit to 1              |00
        skpc                    ; if data bit = 1 skip, else      |00
        xorlw   1<<TxPin        ; set TxPin bit to 0              |00
        movwf   PORTA           ; precise "bit Time" intervals    |00
        decfsz  bitctr,F        ; done? yes, skip, else           |00
        goto    nextbit         ; send next bit                   |00
        return                  ;                                 |00

;******************************************************************
;  delayCy() subsystem iDelay subroutine (8-bit 4-cycle loop)     *
;                               ;**********************************
        nop                     ; entry point for (delay%4) == 3  |00
        nop                     ; entry point for (delay%4) == 2  |00
        nop                     ; entry point for (delay%4) == 1  |00
iDelay  addlw   -1              ; entry point for (delay%4) == 0  |00
        skpz                    ; done? yes, skip, else           |00
        goto    iDelay          ; loop again                      |00
        return                  ; return (Z = 1 and C = 1)        |00

;******************************************************************
        end
MMcLaren
 
Posts: 18
Joined: Sun Aug 31, 2014 10:08 pm
PIC experience: Experienced Hobbyist

Re: PIC10F322 AD Project in Assembly, RS232

Postby Olin Lathrop » Tue Sep 02, 2014 1:05 pm

Tom Maier wrote:... so I just made up a project to make an rs232 line powered streaming AD, and here it is.


  • Nice demo, and it's good to see a decent amount of comments at the top of the file explaining what is going on.

  • You have a pullup resistor on MCLR, but can't the PIC be configured for internal pullup on MCLR? (Other PIC 10 can do this)

  • CBLOCK, really!? You should be ashamed of yourself for giving newbies the impression that CBLOCK is a acceptable way to declare variables. All it creates are enumerated constants. Only you know that some of these constant may be addresses of variables.

  • What's with the ORGs at 4 and 8? This part has no interrupts, and there is no reason you couldn't use the interrupt vector locations for ordinary code if you're not using interrupts even on a processor that has them. On processors that could interrupt, this doesn't save you from anything since execution will still go to 4 or 8, depending on the processor.

  • In general on a 12 bit core part, you want to put subroutines first, then the main code after that. You got away with it here because the size of the whole program is so small.

  • Various hard coded constants for delays is a bad idea, especially since you even document that this is supposed to work with different clock speeds. These constants should be derived at build time from the clock speed setting and the desired delay time. A DELAY macro would have made a lot of sense. This would have used assembly time math to compute the number of busy-wait iterations to get the desired delay time. This would take the one-off entry and exit delays into account too.

I think it's great you are providing a example of a complete PIC project, but it would be even better if it were also a example of good coding practices.
User avatar
Olin Lathrop
Verified identity
 
Posts: 48
Joined: Fri May 30, 2014 3:38 pm
Location: Littleton, MA USA
PIC experience: Professional 5+ years with MCHP products

Re: PIC10F322 AD Project in Assembly, RS232

Postby Tom Maier » Tue Sep 02, 2014 1:36 pm

Hey Olin,

Why don't you post something?

You run your mouth, but not much value comes out.
User avatar
Tom Maier
Verified identity
 
Posts: 179
Joined: Mon May 26, 2014 2:37 pm
PIC experience: Professional 5+ years with MCHP products

Re: PIC10F322 AD Project in Assembly, RS232

Postby Tom Maier » Tue Sep 02, 2014 2:06 pm

And Mike...

Thanls for clearing up the timing issue. Looking back it does seem like i was targeting 109 cycles when i should have been shooting dor 104. I don't know why I had 109 microseconds in my mind at the time.

I did this in two days, using a chip and chip family I was unfamilar with. The two days including coming up with the idea, creating a prototype, writing the documentation, learning the new mplabX environment, reading the pic10 manual, trying to relearn pic assembly, and proving it out in hardware at all baud rates under varying voltage conditions to see if I could get it to crash.

Oddly enough, the baud rate worked even though it was pushed long.
User avatar
Tom Maier
Verified identity
 
Posts: 179
Joined: Mon May 26, 2014 2:37 pm
PIC experience: Professional 5+ years with MCHP products

Next

Return to 12-Bit Core

Who is online

Users browsing this forum: No registered users and 1 guest

cron