Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Misterous lost of bits

Status
Not open for further replies.

Rinus

New Member
I'm having trouble with a PIC16F883. It seems as if I'm losing information.
The PIC is connected to an ancient Pentium 1 laptop via the parallel port. I use 4 bits to write to the status register of the pp (&379). This works fine.
The problem arise on the second nibble that's needs to be sent. At this time it seems as if my storage has been cleared.

I load a register (called dataByte - in the H'70' space - available to all pages) with a byte. I then move this data to another byte (sndDataBt - also in the H'70' space) for swapping.

The byte is then sent in 2 parts to PORTC(4-7), each time indicating ready and waiting for signal from pc that it's ready/complete.

Code:
.
.
.
MOVLW B'11111111'
MOVWF dataByte
CALL SEND_BYTE


SEND_BYTE
BTFSC SNDSTRT ;Part of reset procedure... ignore
RETURN

MOVF dataByte,W ;Read the data to be sent into W
MOVWF sndDataBt ;Store in another place.
SWAPF sndDataBt,F ;Swap nibbles
BANKSEL PORTC
MOVLW B'00001111' ;Clear upper 4 bits of PORTC, but leave
ANDWF PORTC,F ;lower 4 bits unchanged.
MOVLW B'11110000' ;Read upper 4 bits of data into W,
ANDWF sndDataBt,W ;ignoring lower 4 bits.
IORWF PORTC,F ;Set PORTC(4-7) = MSB nibble of data
;(actually LSB, swapf'd)

BCF SREDY ;Set ready to send data indicator. (change in value
;indicates setting...)
BTFSS SNDD ;Wait for PC to set indicator
GOTO $-1

;MOVLW B'11111111' ;Testing attempt to force all high
;MOVWF dataByte ;
MOVLW B'00001111' ;Clear PORTC(4-7)
ANDWF PORTC,F ;
MOVLW B'11110000' ;
ANDWF dataByte,W ;Read MSB nibble from data (should be unchanged,
IORWF PORTC,F ;but at this point it's cleared)

BSF SREDY ;Set ready to send data indicator
RETURN ;All data sent.

Tests I have done:
The code above sets all the bits in dataByte to 1 - I expect that on the pc. For some reason I recieve zeroes in the MSB (second) nibble.
When I set all the bits again - in the commented out code - I do get all the one's. Somewhere along the line the dataByte register seem to have been cleared and I have been pulling out my hair trying to find put how.
I have tested each bit of dataByte seperately and setting the bits of PORTC - not worked.
I have slapped in NOP's, thinking that maybe transmission is faster than the pp can handle - not worked.
I have changed my chip...
Any help/suggtestions are highly appreciated.

Running at 20MHz, using crystal.
PORTC is buffered via LM324 to parallel port.
PORTC,1 is used as PWM
PORTC,2 is used as input for testing - to hold a status for manual continue
PORTC,3 is output indicator to pp

Thanks.
Rinus.
 
hi rinus and welcome,

Please post your full code, use the '#' symbol in the window menu to paste your code, its keeps the formatting.

Eric
 
Full source code of problem...

Hi Eric,
Sorry for the dealy. The laptop is not wireless enabled and this pc does not have a stiffy drive...

Below are both sets of code:

PIC16F883:
Code:
    list p=16f883
#include    <P16F883.INC>

;Current sensor.

    __idlocs    0022

    __CONFIG    _CONFIG1,B'11101111000010'
    __CONFIG    _CONFIG2,B'11111011111111'


Wtmp0 equ H'20'
Wtmp1 equ H'21'
Wtmp2 equ H'22'
Wtmp3 equ H'23'
Wtmp4 equ H'24'
Wtmp5 equ H'25'
Wtmp6 equ H'26'
Wtmp7 equ H'27'
Stmp0 equ H'28'
Stmp1 equ H'29'
Stmp2 equ H'30'
Stmp3 equ H'31'
Stmp4 equ H'32'
Stmp5 equ H'33'
Stmp6 equ H'34'
Stmp7 equ H'35'
TmpDp equ H'36'    ;Indicate the current level of W and Status stack
StrW  equ H'37'
StrS  equ H'38'

    CBLOCK 0x70
        flags
        delayCntr
        delayReq
        currentADC
        voltADCH
        voltADCL
        dataByte
        sndDataBt
        sndDataBt2
        iocData     ;Read entire PORTB on IOC.
    ENDC


#define SNDD    PORTB,4 ;PC Signal to send data.
#define SNDSTRT PORTB,5 ;To indicate start of transmission...
#define SREDY   PORTC,3 ;Ready to receive indicator
#define voltRef B'11100000'

;Command - format: CCCCCCLL   
        ;where CCCCCC is a number representing the command
        ;and   LL is the number of bytes of data to follow. 3 bytes is enough.
        ;Most data to send is 10 bits.... (2 bytes)
#define sndVltCmd1  B'00000110'
#define sndCurCmd1  B'00001010'
#define sndVltCmd2  B'00001110'
#define sndCurCmd2  B'00010010'
#define sndPWMper   B'00010110'

    ORG     H'000' ; start at address 0
    GOTO    mainProgram

    ORG     H'004'
    GOTO    interruptControl

delay
    CALL    pushWorkBSR
    MOVF    delayReq,W
    MOVWF   delayCntr
delayLoop
    NOP
    DECFSZ  delayCntr,f
    GOTO    delayLoop
    CALL    popWorkBSR
    RETURN

pushWorkBSR
    MOVWF   StrW
    MOVF    STATUS,W
    MOVWF   StrS
    INCF    TmpDp,F
    MOVF    TmpDp,W
    ADDWF   PCL,F
    GOTO    LVL0
    GOTO    LVL1
    GOTO    LVL2
    GOTO    LVL3
    GOTO    LVL4
    GOTO    LVL5
    GOTO    LVL6
    GOTO    LVL7
    GOTO    OVERFLOW
LVL0
    MOVF    StrW,W
    MOVWF   Wtmp0
    MOVF    StrS,W
    MOVWF   Stmp0
    RETURN
LVL1
    MOVF    StrW,W
    MOVWF   Wtmp1
    MOVF    StrS,W
    MOVWF   Stmp1
    RETURN
LVL2
    MOVF    StrW,W
    MOVWF   Wtmp2
    MOVF    StrS,W
    MOVWF   Stmp2
    RETURN
LVL3
    MOVF    StrW,W
    MOVWF   Wtmp3
    MOVF    StrS,W
    MOVWF   Stmp3
    RETURN
LVL4
    MOVF    StrW,W
    MOVWF   Wtmp4
    MOVF    StrS,W
    MOVWF   Stmp4
    RETURN
LVL5
    MOVF    StrW,W
    MOVWF   Wtmp5
    MOVF    StrS,W
    MOVWF   Stmp5
    RETURN
LVL6
    MOVF    StrW,W
    MOVWF   Wtmp6
    MOVF    StrS,W
    MOVWF   Stmp6
    RETURN
LVL7
    MOVF    StrW,W
    MOVWF   Wtmp7
    MOVF    StrS,W
    MOVWF   Stmp7
    RETURN
OVERFLOW
    MOVF    Wtmp1,W
    MOVWF   Wtmp0
    MOVF    Stmp1,F
    MOVWF   Stmp0
    MOVF    Wtmp2,W
    MOVWF   Wtmp1
    MOVF    Stmp2,W
    MOVWF   Stmp1
    MOVF    Wtmp3,W
    MOVWF   Wtmp2
    MOVF    Stmp3,W
    MOVWF   Stmp2
    MOVF    Wtmp4,W
    MOVWF   Wtmp3
    MOVF    Stmp4,W
    MOVWF   Stmp3
    MOVF    Wtmp5,W
    MOVWF   Wtmp4
    MOVF    Stmp5,W
    MOVWF   Stmp4
    MOVF    Wtmp6,W
    MOVWF   Wtmp5
    MOVF    Stmp6,W
    MOVWF   Stmp5
    MOVF    Wtmp7,W
    MOVWF   Wtmp6
    MOVF    Stmp7,W
    MOVWF   Stmp6
    MOVF    StrW,W
    MOVWF   Wtmp7
    MOVF    StrS,W
    MOVWF   Stmp7
    DECF    TmpDp,F
    RETURN

popWorkBSR
    MOVF    TmpDp,W
    ADDWF   PCL,F
    GOTO    popLvl0
    GOTO    popLvl1
    GOTO    popLvl2
    GOTO    popLvl3
    GOTO    popLvl4
    GOTO    popLvl5
    GOTO    popLvl6
    GOTO    popLvl7
    RETURN
popLvl0
    MOVF    Stmp0,W
    MOVWF   STATUS
    MOVF    Wtmp0,W
    GOTO    FINISHPOP
popLvl1
    MOVF    Stmp1,W
    MOVWF   STATUS
    MOVF    Wtmp1,W
    GOTO    FINISHPOP
popLvl2
    MOVF    Stmp2,W
    MOVWF   STATUS
    MOVF    Wtmp2,W
    GOTO    FINISHPOP
popLvl3
    MOVF    Stmp3,W
    MOVWF   STATUS
    MOVF    Wtmp3,W
    GOTO    FINISHPOP
popLvl4
    MOVF    Stmp4,W
    MOVWF   STATUS
    MOVF    Wtmp4,W
    GOTO    FINISHPOP
popLvl5
    MOVF    Stmp5,W
    MOVWF   STATUS
    MOVF    Wtmp5,W
    GOTO    FINISHPOP
popLvl6
    MOVF    Stmp6,W
    MOVWF   STATUS
    MOVF    Wtmp6,W
    GOTO    FINISHPOP
popLvl7
    MOVF    Stmp7,W
    MOVWF   STATUS
    MOVF    Wtmp7,W
FINISHPOP
    DECF    TmpDp,F
    RETURN

interruptControl
    BCF     INTCON,GIE
    BTFSC   INTCON,RBIF
    GOTO    HANDLE_IOC


    RETFIE

HANDLE_IOC
    CALL    pushWorkBSR
    BCF     INTCON,RBIE ;Disable IOC interrupt
    BANKSEL PORTB
    MOVF    PORTB,W     ;Read entire PORTB - will also remove mismatch condition
    MOVWF   iocData     ;Store values from PORTB for bit testing
    BCF     INTCON,RBIF ;Clear IOC Flag

    ;Test each IOC bit and handle...
    BTFSS   iocData,4   ;IOC4 - active LOW - request to send data.
    GOTO    SEND_DATA

COMPLETE_IOC
    ;All IOC conditions checked...
    BSF     INTCON,RBIE
    CALL    popWorkBSR
    RETFIE



SEND_DATA
    BSF     iocData,4   ;Set (active LOW) send data flag in IOC stored byte.
    BTFSC   SNDSTRT
    GOTO    COMPLETE_IOC
    MOVLW   B'11111111'
    ;MOVLW   B'10000000'
    MOVWF   dataByte
    CALL    SEND_BYTE
    MOVLW   B'00000000'
    MOVWF   dataByte
    CALL    SEND_BYTE
    MOVLW   B'00000000'
    MOVWF   dataByte
    CALL    SEND_BYTE
    GOTO    COMPLETE_IOC

SEND_BYTE
    BTFSC   SNDSTRT     ;Part of reset procedure... ignore
    RETURN

    MOVF    dataByte,W  ;Read the data to be sent into W
    MOVWF   sndDataBt   ;Store in another place.
    SWAPF   sndDataBt,F ;Swap nibbles
    BANKSEL PORTC
    MOVLW   B'00001111' ;Clear upper 4 bits of PORTC, but leave
    ANDWF   PORTC,F     ;lower 4 bits unchanged.
    MOVLW   B'11110000' ;Read upper 4 bits of data into W,
    ANDWF   sndDataBt,W ;ignoring lower 4 bits.
    IORWF   PORTC,F     ;Set PORTC(4-7) = MSB nibble of data
                        ;(actually LSB, swapf'd)

    BCF     SREDY       ;Set ready to send data indicator. (change in value
                        ;indicates setting...)
    BTFSS   SNDD        ;Wait for PC to set indicator
    GOTO    $-1

    ;MOVLW   B'11111111' ;Testing attempt to force all high
    ;MOVWF   dataByte    ;
    MOVLW   B'00001111' ;Clear PORTC(4-7)
    ANDWF   PORTC,F     ;
    MOVLW   B'11110000' ;
    ANDWF   dataByte,W  ;Read MSB nibble from data (should be unchanged,
    IORWF   PORTC,F     ;but at this point it's cleared)

    BSF     SREDY       ;Set ready to send data indicator
    RETURN              ;All data sent.

mainProgram
    BANKSEL PORTA ;
    CLRF    PORTA ;Init PORTA
    BANKSEL ANSEL ;
    CLRF    ANSEL ;digital I/O
    BSF     ANSEL,ANS0 ;AN0 - Current sensor ADC input.
    BSF     ANSEL,ANS1 ;AN1 - Voltage sensor ADC input.
    BSF     ANSEL,ANS3 ;AN3 - ADC +ref.
;    BSF     ANSELA,ANSA2 ;AN2 - Vref+ - max from opamp.

;set PORTB all digital output:
    BANKSEL PORTB
    CLRF    PORTB
    BANKSEL ANSELH
    CLRF    ANSELH
    BANKSEL TRISB
    CLRF    TRISB
    BSF     TRISB,4 ;Send data signal from PC.
    BSF     IOCB,4  ;Set IOC for interrupt from PC.
    BSF     TRISB,5 ;To sence start-of-transmission.

;Setup PWM2:
;Settings: Freq: 150kHz
; - Timer Prescale = 1
; - PR2 = 0x1F
; - MAX bits: 7
    ;Disable PWM output:
    BANKSEL PORTC
    CLRF    PORTC
    BANKSEL TRISC
    CLRF    TRISC
    BSF     TRISC,1
    BSF     TRISC,2
    ;Load PR2:
    ;BANKSEL PR2 - same bank as TRIS C
    MOVLW   H'8F'
    MOVWF   PR2
    ;Config PWM2 by loading CCP2CON:
    BANKSEL CCP2CON
    MOVLW   B'00001100'
    MOVWF   CCP2CON
    ;Set PWM duty cycle:
    ;BANKSEL CCPR2L - same bank as CCP2CON
    CLRF    CCPR2L
    ;--LSB 2 bits in CCP2CON already cleared.
    ;Confure and start Timer2:
    ;--PIR1 in same bank as CCPR2L
    BCF     PIR1,TMR2IF
    CLRF    T2CON
    ;bsf     T2CON,1 ; for testing - set to prescal 1:16
    clrf    TMR2
    NOP
    NOP
    BSF     T2CON,TMR2ON
    BTFSS   PIR1,TMR2IF
    GOTO    $-1
    BANKSEL TRISC
    BCF     TRISC,1
;PWM2 Setup Complete - To use increase duty cycle.


    ;Setup ADC as current sensor input from PORTA0:
    ;Use program up to Loop for acquisition delay.
    banksel ADCON1
    movlw   B'00000000'
        ;Left justified,Fosc/64,Vref- = VSS,Vref+ = VDD (5V)
    movwf   ADCON1
    banksel ADCON0
    movlw   B'10000001';Select Channel AN0(PORTA0) and switch on
    movwf   ADCON0
    ;ADC setup complete on PORTA0.


    ;Enable Interrupts:
    MOVF    PORTB,W     ;Read PORTB to remove mismatch contitions
    BCF     INTCON,RBIF ;Clear IOC Flag
    BSF     INTCON,RBIE ;Enable IOC on PORTB.
    BSF     INTCON,GIE  ;Enable all interrupts.

    ;Initialize:
    CLRF    TmpDp
    BSF     SREDY


Loop
    movlw   H'FF'
    movwf   delayReq
    call    delay
    goto    Loop

    end

C++ code on PC:
Code:
#include "conio.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "dos.h"
#include "graphics.h"
#include "time.h"


short readByte() {
  short data,rdNib,readyCk,val=0;
  outp(0x378,1);
  int cntr=0,cont=0,timeout=0;
  int timeOutCntr=0;

  data = 0;
  outp(0x378,0);
  cont = 0;
  timeOutCntr = 0;

  timeout = 0;
  while(cont==0) {
    data = inp(0x379);
//    printf("data1 :%d ",data);
    data = inp(0x379);
//    printf("data11:%d ",data);
    data = inp(0x379);
//    printf("data12:%d\n ",data);
    cont = data & 128;
//      printf("in while 1 data read:%d\n",data);
//      timeout = 0;
//      if (timeOutCntr > 20) {
//	timeout=1;
//	break;
//      }
    delay(1);
//      timeOutCntr++;
  }
   // printf("afta wile 1\n");
 //   if (timeout == 1) {
 //     outp(0x378,1);
 //     timeout = 0;
 //     delay(100);
 //   } else {
  data = inp(0x379);
  printf("while1 read:%d ",data);
  data = data >> 3;
  printf("while1 shifted:%d ",data);
  val = data & 15;
  printf("while1 val:%d\n",val);

 //   }
  outp(0x378,1);
  cont = 1;
  timeout = 0;
  timeOutCntr = 0;
 //   printf("going to start while 2\n");
  while(cont!=0) {
 //     printf("iun while 2\n");
    data = inp(0x379);
 //   printf("data1 :%d ",data);
    data = inp(0x379);
 //   printf("data11:%d ",data);
    data = inp(0x379);
 //   printf("data12:%d\n ",data);
    cont = data & 128;
 //     if (timeOutCntr > 20) {
 //	timeout=1;
 //	printf("timeout 2 occured\n");
 //	break;
 //     }
    delay(1);
    timeOutCntr++;
  }
  data = inp(0x379);
  printf("whil2 read:%d ",data);
  data = data << 1;
  printf("whil2 shifted:%d ",data);
  data = data & 240;
  printf("whil2 anded:%d ",data);
  val = val | data;
  printf("final val:%d\n",val);
  outp(0x378,0);
  delay(1);
  outp(0x378,1);

  data = 1;
  return val;
}

int main(int argc,char* argv[])
{
  short inCmd,inByte1,inByte2;
  outp(0x378,3);
  delay(1);
  outp(0x378,2);
  delay(1);
  outp(0x378,3);
  delay(1);
  outp(0x378,2);
  delay(1);
  outp(0x378,3);
  delay(1);
  outp(0x378,2);
  delay(1);
  outp(0x378,3);
  delay(1);
  outp(0x378,2);
  delay(1);
  outp(0x378,3);
  delay(1);
  outp(0x378,1);

  for(int xx=0;xx<5;xx++) {
    inCmd = readByte();
    inByte1 = readByte();
    inByte2 = readByte();
    printf("Command:%d   Byte1:%d    Byte2:%d \n",inCmd,inByte1,inByte2);
    delay(100);
  }
  return 0;
}

I built an interface for the parallel port, so I cannot give you the precise pin-to-pin connections, but I can say that I use the STATUS register (&379) bits 3-6 for input, bit 7 for ready ind from PIC and DATA (&378) bits 0 and 1 for output to the PIC. DATA 0 is the READY indicator and DATA 1 is the reset pin. On the PIC side I use PORTB 4 send indicator and PORTB 5 as the reset line.

Regards
Rinus.
 
hi Rinus,
Copied your assembly Code, it compiles OK, I will run it thru my Oshonsoft simulator, let you know if I get a solution.

E.
 
hi Rinus,
It appears that during the SEND routines, PORTC is configured as Inputs.???

E.

EDIT:
I expect you know I have to bypass sections of the Code in the Sim, I bypassed an Init fragment, so ignore the above finding, still looking.
 
Last edited:
hi,
I have modified your code to run this fragment in simulation, it runs OK, all '1s' on PORTC4/7 for both nibbles.
I had to change the B'xxxxxxxx' to hex values as my assembler would not recognise the 'B' version.

E

EDIT:

As a double check loaded with MOVLW 0x5A.

The low nibble 'A' is sent first followed by the high nibble '5'


Code:
; problem code area  
SEND_DATA
    BSF     iocData,4   ;Set (active LOW) send data flag in IOC stored byte.
    BTFSC   SNDSTRT
 ;;   GOTO    COMPLETE_IOC

;************
    MOVLW   0xff;;B'11111111'
  MOVLW  0xff;;;B'11111111';+++
    ;MOVLW   B'10000000'
    MOVWF   dataByte
    CALL    SEND_BYTE;   
    MOVLW   0x00;;;;B'00000000'
    MOVWF   dataByte
    CALL    SEND_BYTE
    MOVLW   0x00;;;B'00000000'
    MOVWF   dataByte
    CALL    SEND_BYTE
   ;; GOTO    COMPLETE_IOC
 
SEND_BYTE
    BTFSC   SNDSTRT     ;Part of reset procedure... ignore
  ;;  RETURN
    MOVF    dataByte,W;++++
    MOVF    dataByte,W  ;Read the data to be sent into W
    MOVWF   sndDataBt   ;Store in another place.
    SWAPF   sndDataBt,F ;Swap nibbles
    BANKSEL PORTC

    MOVLW   0x0f;;B'00001111' ;Clear upper 4 bits of PORTC, but leave
    ANDWF   PORTC,F     ;lower 4 bits unchanged.
    MOVLW   0xf0;;;B'11110000' ;Read upper 4 bits of data into W,
    ANDWF   sndDataBt,W ;ignoring lower 4 bits.
    IORWF   PORTC,F     ;Set PORTC(4-7) = MSB nibble of data
                        ;(actually LSB, swapf'd)
 
    BCF     SREDY       ;Set ready to send data indicator. (change in value
                        ;indicates setting...)
    BTFSS   SNDD        ;Wait for PC to set indicator
;;;    GOTO    $-1
 
    ;MOVLW   B'11111111' ;Testing attempt to force all high
    ;MOVWF   dataByte    ;
    MOVLW   0x0f;;B'00001111' ;Clear PORTC(4-7)
    ANDWF   PORTC,F     ;
    MOVLW   0xf0;;B'11110000' ;
    ANDWF   dataByte,W  ;Read MSB nibble from data (should be unchanged,
    IORWF   PORTC,F     ;but at this point it's cleared)
 
    BSF     SREDY       ;Set ready to send data indicator
    RETURN              ;All data sent.

;***************************
 
Last edited:
Hi Eric,

Thanks. I'll try it when I get home. I was suddenly and "forcefully" :) drawn away to my in-laws...

Will post my finding later tonight.

Thanks for your help.

Rinus.
 
Hi Eric,

Nope, using hex i.s.o. binary makes no difference. (I kind of expected it though).
What I did find was if I copied the following 2 lines into the SEND_BYTE routine, it does work, but not if they appear before the CALL, even immediately before.

MOVLW H'FF'
MOVWF dataByte

But that renders the SEND_BYTE routine irrelvant. I need to set the dataByte before calling it.

It is a relieve to hear that it does work on your simmulator - it means that there's a chance it's not my code. :)

Getting the full H'FF' value on the laptop when it's moved there in the SEND_BYTE routine also indicates that the laptop is receiving the data correctly as sent by the PIC.

That leaves me with the idea that it's got something to do with the CALL statement.

The program is so small that the page boundaries for the flash program memory are not crossed.

The registers in use in the general purpose registers accessible from all pages (0x70 - 0x7F) space, numbers only 10. There is also no chance of crossing page boundaries.

Since this is working in your simulator it must be hardware realted. But I get exactly the same result using different chips.

I'll keep on hammering away, but I am kind of running out of ideas.

Regards
Rinus.
 
Hi Eric,

I think the bug lies somewhere in the syncronization between laptop and PIC.

I'll look again tomorrow night.

Cheers
Rinus.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top