PIC 18F4550 and MCP23017


Closed Thread
Results 1 to 13 of 13

Hybrid View

  1. #1
    Join Date
    Mar 2008
    Location
    Gerogetown, Texas
    Posts
    94

    Default PIC 18F4550 and MCP23017

    I have seen some questions about using a port expanders, here is a version that works for the MCP23017, I am using MicroChip's USB boot loader. This program simply sets the 23017's PortA as inputs and PortB as outputs (driving LEDs). It also send the PortA value to the PC via USB.

    Code:
    define LOADER_USED 1        ' USB Boot loader
    define RESET_ORG 800h
    define INTERRUPT_ORG 808h
    DEFINE OSC 48
    DEFINE I2C_SCL PORTA,1
    DEFINE I2C_SDA PORTA,0
    Define I2C_SLOW 1     'At this clock speed this needed to be added to make it work.
    
    
    'define SHIFT_PAUSEUS 200
    ADCON1 = $F       'port A digital
    CMCON = 7         'PortA Digital
    
    USBBufferSizeMax   con 16  ' maximum buffer size
    USBBufferSizeTX    con 16  ' input 
    USBBufferSizeRX    con 16  ' output
    
    ' the USB buffer...
    USBBuffer        Var Byte[USBBufferSizeMax] 
    USBBufferOut     Var Byte[USBBufferSizeMax]
    USBBufferCount   Var Byte 
    Addr             var byte
    j                var byte
    i                var byte
    
    '======================================================================================
    ' Port A Registers (8 Bit Mode)
    IODIRA             con   $00          ' Direction Bit Control Reg
    IOBITSA            con	%11111111	' Direction Bit Settings Reg (0 = output, 1 = input)
    IPOLA              con	$01			' Interrupt Polarity Control Reg
    GPINTENA           con	$02			'Interrupt Enable Reg
    DEFVALA            con	$03
    INTCONA	           con	$04
    IOCONA	           con	$05			' I/O Configuration Reg
    IOCONSETA          con	%10111000	' IOCON register setting
    GPPUA	           con	$06			' Pull-Up Control Reg
    INTFA	           con	$07			' Interrupt Flag Register
    INTCAPA	           con	$08
    GPIOA	           con	$09			' General Purpose I/O
    IOLATA	           con	$0A			' Output Latch Reg
    
    'Port B Registers (8 Bit Mode)
    IODIRB	          con	$10			' Port B Direction Bit Control Address
    IOBITSB	          con	%00000000		' Port B Direction Bit Settings (0 = output, 1 = input)
    IPOLB	          con	$11			' Interrupt Polarity Control
    GPINTENB          con	$12			' Interrupt Enable Reg
    DEFVALB	          con	$13
    INTCONB	          con	$14
    IOCONB	          con	$15			' I/O Configuration Reg
    IOCONSETB         con	%10111000		' IOCON register setting
    GPPUB	          con	$16			' Pull-Up Control Reg
    INTFB	          con	$17			' Interrupt Flag Register
    INTPOLB	          con	$18
    GPIOB	          con	$19			' General Purpose I/O Reg
    IOLATB	          con	$1A			' Output Latch Reg
    
    '========================================================================================
    ' Port A Reguisters (16 Bit Mode)
    IODIRA16            con	    $00
    IODIRB16            con	    $01
    IOCONA16            con	    $0A
    IOCONB16            con	    $0B
    GPIOA16             con		$12
    GPIOB16             con		$13
    OLATA16             con		$14
    OLATB16             con		$15
    
    IO_EXP0WR           con	    $4E		' MCP23017  Write
    IO_EXP0RD           con	    $4F		' MCP23017  Read
    IO_DAT              var     byte    ' MCP23017  Data read
    IO_DAT_OLD          var     byte
    Out_Dat             var     byte
        '   Interrupt definition   
        '   ====================
            '   USB interrupt used to keep USB connection alive
    INCLUDE "DT_INTS-18.bas"    ' Base Interrupt System
    INCLUDE "ReEnterPBP-18.bas"     ' Include if using PBP interrupts
    ASM
    INT_LIST  macro    ; IntSource,         Label,  Type, ResetFlag?
            INT_Handler    USB_INT,  _DoUSBService,   ASM,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    usbinit ' initialise USB...
    USBService                                    ' keep connection alive
    UIE = $7F
    UEIE = $9F
    @   INT_ENABLE  USB_INT
    gosub InitMPC23017
    gosub ReInitPortA
    goto Programstart
    ' ************************************************************
    ' * Sub-routines                                             *
    ' ************************************************************
    DoUSBService:    'Keeps USB alive
        usbservice
    @   INT_RETURN
    
    
    ' ************************************************************
    ' * receive data from the USB bus                            *
    ' ************************************************************
    DoUSBIn:
       USBBufferCount = USBBufferSizeRX              ' RX buffer size
       'USBService                                    ' keep connection alive
       USBIn 1, USBBuffer, USBBufferCount, DoUSBIn   ' read data, if available
       return
        
    ' ************************************************************
    ' * wait for USB interface to attach                         *
    ' ************************************************************
    DoUSBOut:
       USBBufferCount = USBBufferSizeTX              ' TX buffer size
       'USBService                                    ' keep connection alive
       USBOut 1, USBBufferout, USBBufferCount, DoUSBOut ' if bus available, transmit data
       return
       
    InitMPC23017:
    Pause 100
    '#############  PORTA
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOCONA,IOCONSETA]
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IODIRA,$0]          'PortA inputs
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOLATA,$FF]            'PortA = 0
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IPOLA,0]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[DEFVALA,0]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[GPPUA,$FF]           'pull-ups enabled
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[INTCONA,0]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[GPINTENA,$FF]        'interupt on change
    '##############  PORTB
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOCONB,IOCONSETB]
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IODIRB,0]
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOLATB,$FF]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IPOLB,0]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[DEFVALB,0]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[INTCONB,0]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[GPINTENB,0]
    return
    ReInitPortA:
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOCONA,IOCONSETA]
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IODIRA,$FF] 
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[GPPUA,$FF]           'pull-ups enabled
    
    return
    
    
    ' ************************************************************
    ' * main program loop - remember, you must keep the USB      *
    ' * connection alive with a call to USBService every couple  *
    ' * of milliseconds or so...                                 *
    
    ProgramStart: 
       'gosub DoUSBIn
       'gosub DoUSBOut
    i2cwrite PortA.0,PortA.1,IO_EXP0wr,[gpioa]
    i2cread PortA.0,PortA.1,IO_EXP0rd,[IO_dat] 
    if IO_DAT_OLD != io_dat then
    ''''   usbbufferout(0) = io_dat
       for j = 0 to 15
      usbbufferout(j) = io_dat
       next j
       gosub  dousbout
     out_dat = io_dat
       io_dat_old = io_dat
    
    endif
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[gpioB,out_dat]
    PAUSE 250
    ''i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[gpioB,0]
    ''PAUSE 250   
       
    goto ProgramStart  
    
       end
    Thanks

    Dave

  2. #2
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    I have not played with USB much.
    This is something I will study from.
    Thanks
    Dave
    Always wear safety glasses while programming.

  3. #3
    Join Date
    Nov 2010
    Posts
    5


    Did you find this post helpful? Yes | No

    Default

    Hey Dave,
    Im trying to use 16f877a with macp23017, but I wasn't successful.
    I define the mcp23017 register, but when I want to compile my program it gives me error.
    I tried to use your program and learn from it but I had no success, I noticed you are using some include file that I dont have them.
    I have 16 led on each port would you please help me?

    Code:
    '*  Notes   :  XT 4Mhz                                          *
    '*          :                                                   *
    '****************************************************************
    'Includes 
    include "modedefs.bas" 
    '****************************************************************
    'Definitions
    DEFINE I2C_SDA PORTc,4 
    DEFINE I2C_SCL PORTc,3   
    '****************************************************************
    'Variables
    a var byte
    chip1 var byte
    chip2 var byte
    chip3 var byte
    chip4 var byte         
    '****************************************************************
    'Alias
    CP VAR PORTc.3
    DP VAR PORTc.4
                             
    '****************************************************************
    'Initialization
    
        'Pic 16f877A
    option_reg.7 = 0 'portb pullups enabled         
    SSPSTAT=%00111101
    'SSPCON1=%00101111
    SSPCON2=%00000001
    
        'MCP 23017
    
    IODIRA Con $00
    IODIRB con $00
    IPOLA con $00
    IPOLB con $00
    GPINTENA con &00
    GPINTENB con $00
    DEFVALA con $00
    DEFVALB con $00
    INTCONA con &00
    INTCONB con &FF
    IOCON con %00001000
    GPPUA con $00
    GPPUB con $00
    INTFA con $00
    INTFB con $00
    INTCAPA con &00
    INTCAPB con &00
    GPIOA con $00
    GPIOB Con $FF
    OLATA con $00
    OLATB con &FF  
    
    '****************************************************************
    'set ports   
         trisa=%00000000             
         trisc=%00000000     
         pause 500                 
         goto start          
    start:
        porta.5 = 1
        portc.7=0
        pause 500
        porta.5 = 1
        portc.7=1
        pause 500
        I2CWRITE dp,cp,$00,chip1,[%00000000] 'one-shot sample
        pause 200
        I2CWRITE dp,cp,$00,chip1,[%11111111] 'one-shot sample 
        pause 200
        I2CWRITE dp,cp,$00,chip1,[%00000000] 'one-shot sample
        pause 200
        I2CWRITE dp,cp,$00,chip1,[%11111111] 'one-shot sample 
        pause 200
         goto start   
    end
    Last edited by ScaleRobotics; - 27th November 2010 at 16:09. Reason: added code tags

  4. #4
    Join Date
    Mar 2008
    Location
    Gerogetown, Texas
    Posts
    94


    Did you find this post helpful? Yes | No

    Default

    What errors are you getting?

    The include files are for USB

    Dave

  5. #5
    Join Date
    Nov 2010
    Posts
    5


    Did you find this post helpful? Yes | No

    Default

    Thanks Dave,

    before i used to define 16f877a register like ( adcon = $82), so i thought it should be same to define mcp registers like (IODIRA = $00 to make my mcp port a as output), I got my first error there ( syntax error, red color on my whole line) then I saw that you define by constant. so i changed my method and followed you and defined the by using "con". but something happens that I dont understand it gives me error when i define GPINTENA con &00, but it accepts GPINTENB con &00 after seeing this I told myself ok im going to use assembly language and i will insert it to my Picbasic as a sub routin. I know that i have to Equate all register and variable like ( eecon1 equ h'08' ) but I think those are for my pic and i dont know how i shoud have access to MCP register to for example turn the pull ups on or off
    I think I'm totally lost. I thought that i define my chip one time (which pin is input and which one output, interrupts, pull ups,..., and then I can use I2CWRITE and read command to send my bytes to the outputs and then read from it.
    how would you do that?

    Thanks for your time, I really appreciate it
    Artha

  6. #6
    Join Date
    Mar 2008
    Location
    Gerogetown, Texas
    Posts
    94


    Did you find this post helpful? Yes | No

    Default

    I think you have a typo error

    GPINTENA con &00 should be GPINTENA con $00

    Try that

    Dave

    You also need to initialize the MCP23017
    Code:
    InitMPC23017:
    Pause 100
    '#############  PORTA
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOCONA,IOCONSETA]
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IODIRA,$0]          'PortA inputs
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOLATA,$FF]            'PortA = 0
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IPOLA,0]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[DEFVALA,0]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[GPPUA,$FF]           'pull-ups enabled
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[INTCONA,0]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[GPINTENA,$FF]        'interupt on change
    '##############  PORTB
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOCONB,IOCONSETB]
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IODIRB,0]
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOLATB,$FF]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IPOLB,0]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[DEFVALB,0]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[INTCONB,0]
    'i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[GPINTENB,0]
    return
    ReInitPortA:
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IOCONA,IOCONSETA]
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[IODIRA,$FF] 
    i2cwrite  PortA.0,PortA.1,IO_EXP0WR,[GPPUA,$FF]           'pull-ups enabled
    
    return
    Last edited by ScaleRobotics; - 27th November 2010 at 16:11. Reason: changed [code end] typo

Members who have read this thread : 2

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts