Advertisement
chasxmd

1-wire PIC starter

Jan 1st, 2015
214
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.66 KB | None | 0 0
  1. /*
  2.  * File:   main.c
  3.  * Author: Charles M Douvier
  4.  * Contact at: http://iradan.com
  5.  *
  6.  * Created on Janurary 1, 2015
  7.  *
  8.  * Target Device:
  9.  * 18F14K22 on Tautic 20 pin dev board
  10.  *
  11.  * Project: Maxim 1-Wire Testing
  12.  *
  13.  * Details of 1-wire protocol using Microchip AN1199
  14.  * Field device http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf
  15.  * The 1-Wire Protocol is registered trade mark of Dallas/Maxim semiconductor.
  16.  *
  17.  * Some code was use by the AN1199 App Note Source code; I got stuck looking for a fast way of txing by bit-bang (yes never did this before)
  18.  * The agreement below mentions a license agreement accompaning this software; There was none. I'll note where this software was used if you
  19.  * want to re-write without the Microchip bits.
  20.  * The Microchip licensing as follows:
  21.  *
  22.  *  * FileName:        1wire.c
  23.  * Dependencies:
  24.  * Processor:       PIC18
  25.  * Complier:        MCC18 v3.13
  26.  * Company:         Microchip Technology, Inc.
  27.  *
  28.  * Software License Agreement
  29.  *
  30.  * Copyright Β© 2004-2007 Microchip Technology Inc.  All rights reserved.
  31.  *
  32.  * Microchip licenses to you the right to use, copy and distribute Software
  33.  * only when embedded on a Microchip microcontroller or digital signal
  34.  * controller and used with a Microchip radio frequency transceiver, which
  35.  * are integrated into your product or third party product (pursuant to the
  36.  * sublicense terms in the accompanying license agreement).  You may NOT
  37.  * modify or create derivative works of the Software.
  38.  *
  39.  *
  40.  * You should refer to the license agreement accompanying this Software for
  41.  * additional information regarding your rights and obligations.
  42.  *
  43.  * SOFTWARE AND DOCUMENTATION ARE PROVIDED β€œAS IS” WITHOUT WARRANTY OF ANY
  44.  * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY
  45.  * OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR
  46.  * PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED
  47.  * UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF
  48.  * WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR
  49.  * EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT,
  50.  * PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
  51.  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY
  52.  * THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER
  53.  * SIMILAR COSTS.
  54.  *
  55.  *
  56.  *
  57.  * Version:
  58.  * 0.1  Configuration, with reset test
  59.  * 0.2
  60.  *
  61.  */
  62. #ifndef _XTAL_FREQ
  63. #define _XTAL_FREQ 16000000 //4Mhz FRC internal osc
  64. #define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
  65. #define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
  66. #endif
  67.  
  68. #include <xc.h>
  69. #include <stdio.h>
  70. #include <stdlib.h>
  71. #include <string.h>
  72.  
  73.  
  74. //config bits
  75. #pragma config FOSC=IRC, WDTEN=OFF, PWRTEN=OFF, MCLRE=ON, CP0=OFF, CP1=OFF, BOREN=ON
  76. #pragma config STVREN=ON, LVP=OFF, HFOFST=OFF, IESO=OFF, FCMEN=OFF
  77.  
  78. #define _XTAL_FREQ 16000000 //defined for delay
  79.  
  80. /*
  81.  * Variables
  82.  */
  83.  
  84.     long int    decm;           //long temp
  85.     int     device_present;
  86.     int     i, ilevel, an4_value;                  //temp
  87.     int     itxdata, txdata;            //int RS232 tx data
  88.     char    buf[10];            //buff for iota
  89.     volatile unsigned int uart_data;    // use 'volatile' qualifer as this is changed in ISR
  90.  
  91. /*
  92.  *  Functions
  93.  */
  94.  
  95.     void interrupt ISR() {
  96.  
  97.     if (PIR1bits.RCIF)          // see if interrupt caused by incoming data .. unused currently
  98.     {
  99.         uart_data = RCREG;     // read the incoming data
  100.         PIR1bits.RCIF = 0;      // clear interrupt flag
  101.                                 //
  102.     }
  103.     // I left this timer interrupt if I needed it later. This is unused.
  104.     if (PIR1bits.TMR1IF)
  105.     {
  106.         //T1CONbits.TMR1ON = 0;
  107.         PIR1bits.TMR1IF = 0;
  108.         //T1CONbits.TMR1ON = 1;
  109.  
  110.     }
  111. }
  112.  
  113.  
  114.      void __delay_10ms(unsigned char n)     //__delay functions built-in can't be used for much at this speed... so!
  115.  {
  116.      while (n-- != 0) {
  117.          __delay_ms(10);
  118.      }
  119.  }
  120.  
  121.  
  122. void uart_send (unsigned int mydata_byte) {      //bytes
  123.  
  124.     while(!TXSTAbits.TRMT);    // make sure buffer full bit is high before transmitting
  125.     TXREG = mydata_byte;       // transmit data
  126. }
  127.  
  128. void write_uart(const char *txt)                //strings
  129. {
  130.                                 //this send a string to the TX buffer
  131.                                 //one character at a time
  132.        while(*txt)
  133.        uart_send(*txt++);
  134. }
  135.  
  136. void serial_init(void)
  137. {
  138.  
  139.     // calculate values of SPBRGL and SPBRGH based on the desired baud rate
  140.     //
  141.     // For 8 bit Async mode with BRGH=0: Desired Baud rate = Fosc/64([SPBRGH:SPBRGL]+1)
  142.     // For 8 bit Async mode with BRGH=1: Desired Baud rate = Fosc/16([SPBRGH:SPBRGL]+1)
  143.  
  144.  
  145.  
  146.     TXSTAbits.BRGH=1;       // select low speed Baud Rate (see baud rate calcs below)
  147.     TXSTAbits.TX9=0;        // select 8 data bits
  148.     TXSTAbits.TXEN=1;     // enable transmit
  149.     BAUDCONbits.BRG16=0;
  150.  
  151.     RCSTAbits.SPEN=1;       // serial port is enabled
  152.     RCSTAbits.RX9=0;        // select 8 data bits
  153.     RCSTAbits.CREN=1;       // receive enabled
  154.  
  155.  
  156.     SPBRG=25;               //38,400bps-ish
  157.                             //BRG16=0, 7=31.25k, 25=9.615k
  158.  
  159.     PIR1bits.RCIF=0;        // make sure receive interrupt flag is clear
  160.     PIE1bits.RCIE=1;        // enable UART Receive interrupt
  161.  
  162.  
  163.          __delay_ms(10);        // give time for voltage levels on board to settle
  164.  
  165. }
  166.  
  167.  
  168. void init_io(void) {
  169.     ANSEL = 0x00;         // no A/D
  170.     ANSELH = 0x00;
  171.  
  172.     TRISAbits.TRISA0 = 0; // output
  173.     TRISAbits.TRISA1 = 0; // output
  174.     TRISAbits.TRISA2 = 0; // output
  175.     TRISAbits.TRISA4 = 0; // output
  176.     TRISAbits.TRISA5 = 0; // output
  177.  
  178.  
  179.  
  180.     TRISBbits.TRISB4 = 0; // RB4 = nc
  181.     TRISBbits.TRISB5 = 1; // RB5 = nc
  182.     TRISBbits.TRISB6 = 0; // RB6 = nc
  183.     TRISBbits.TRISB7 = 0; // RB7 = nc
  184.  
  185.     LATC = 0x00;
  186.  
  187.     TRISCbits.TRISC0 = 1; // AN4
  188.     TRISCbits.TRISC1 = 1; // 1-wire data
  189.     TRISCbits.TRISC2 = 0; // Enable Drive
  190.     TRISCbits.TRISC3 = 0; // Direction
  191.     TRISCbits.TRISC4 = 0; // Driver Output Test
  192.     TRISCbits.TRISC5 = 0; // PWM output
  193.     TRISCbits.TRISC6 = 1; // input
  194.     TRISCbits.TRISC7 = 1; // input
  195.  
  196. }
  197.  
  198.  
  199. void init_adc (void)
  200. {
  201.     ANSELbits.ANSEL4=1;         //PORTC.0
  202.     ADCON2bits.ADCS = 0x02;     //Fosc/32
  203.     ADCON2bits.ADFM=0;          //left
  204.     ADCON1=0x00;
  205. }
  206.  
  207. void read_adc (void)
  208. {
  209.     ADCON0bits.CHS0 = 0;        // AD4
  210.     ADCON0bits.CHS1 = 0;
  211.     ADCON0bits.CHS2 = 1;
  212.     ADCON0bits.CHS3 = 0;
  213.     ADCON0bits.ADON = 1;        // A/D ON
  214.     __delay_us(5);
  215.  
  216.     ADCON0bits.GO   = 1;        // ..GO!
  217.  
  218.     __delay_us(5);
  219.  
  220.         while (ADCON0bits.GO) continue;              //wait for conversion
  221.         an4_value = ADRESH;                          //AN4 value
  222. }
  223.  
  224. void one_wire_reset(void) {
  225.     device_present = 0x00;
  226.     TRISCbits.TRISC1 = 0;
  227.     LATCbits.LATC1 = 0;
  228.     __delay_us(240);        //delay 480 us
  229.     __delay_us(240);
  230.     TRISCbits.TRISC1 = 1;
  231.     __delay_us(70);
  232.     if (!PORTCbits.RC1) {
  233.             device_present = 0x01;
  234.     }
  235.     __delay_us(205);        //delay 410 us
  236.     __delay_us(205);
  237. }
  238.  
  239. //this looks a lot like the Microchip code, it was not I just happened to be on the right track.
  240. void one_wire_tx_bit(unsigned char txbit) {         // write a bit
  241.     if (txbit) {
  242.     TRISCbits.TRISC1 = 0;
  243.     LATCbits.LATC1 = 0;
  244.     __delay_us(6);    
  245.     TRISCbits.TRISC1 = 1;
  246.     __delay_us(64);      
  247.     }
  248.     else {      
  249.     TRISCbits.TRISC1 = 0;
  250.     LATCbits.LATC1 = 0;
  251.     __delay_us(60);    
  252.     TRISCbits.TRISC1 = 1;
  253.     __delay_us(10);    
  254.     }
  255. }
  256.  
  257. //from Microchip AN1199 code, renamed and slightly modified to match my software
  258. /**********************************************************************
  259. * Function:        void OW_write_byte (unsigned char write_data)
  260. * PreCondition:    None
  261. * Input:           Send byte to 1-wire slave device
  262. * Output:          None
  263. * Overview:        This function used to transmit a complete byte to slave device.
  264. *                  
  265. ***********************************************************************/
  266. void one_wire_tx_byte (unsigned char write_data)
  267. {
  268.     unsigned char loop;
  269.    
  270.     for (loop = 0; loop < 8; loop++)
  271.     {
  272.         one_wire_tx_bit(write_data & 0x01);     //Sending LS-bit first
  273.         write_data >>= 1;                   // shift the data byte for the next bit to send
  274.     }  
  275. }  
  276.  
  277.  
  278. //from Microchip AN1199 code: I gathered the essence of this but seeing as I am not using most of the AN1199 code
  279. //and this would not work with XC8 I had to re-write this.
  280. /**********************************************************************
  281. * Function:        unsigned char OW_read_bit (void)
  282. * PreCondition:    None
  283. * Input:           None
  284. * Output:          Return the status of the OW PIN
  285. * Overview:        This function used to read a single bit from the slave device.
  286. *                  
  287. ***********************************************************************/
  288.  
  289. unsigned char one_wire_rx_bit (void)
  290. {
  291.     unsigned char read_data;
  292.         read_data = 0x00;
  293.     //reading a bit
  294.     TRISCbits.TRISC1 = 0;
  295.         LATCbits.LATC1 = 0;                         // Drive the bus low
  296.     __delay_us(6);                      // delay 6 microsecond (us)
  297.     TRISCbits.TRISC1 = 1;                       // Release the bus
  298.     __delay_us(9);                      // delay 9 microsecond (us)
  299.  
  300.         if (PORTCbits.RC1) {                                    //read 1 or 0
  301.             read_data = 0x01;
  302.         }
  303.  
  304.     __delay_us(55);                     // delay 55 microsecond (us)   
  305.     return read_data;
  306. }
  307.  
  308.  
  309. /**********************************************************************
  310. * Function:        unsigned char OW_read_byte (void)
  311. * PreCondition:    None
  312. * Input:           None
  313. * Output:          Return the read byte from slave device
  314. * Overview:        This function used to read a complete byte from the slave device.
  315. *                  
  316. ***********************************************************************/
  317.  
  318. unsigned char one_wire_rx_byte (void)
  319. {
  320.     unsigned char loop, result=0;
  321.    
  322.     for (loop = 0; loop < 8; loop++)
  323.     {
  324.        
  325.         result >>= 1;               // shift the result to get it ready for the next bit to receive
  326.         if (one_wire_rx_bit())
  327.         result |= 0x80;             // if result is one, then set MS-bit
  328.     }
  329.     return result;                 
  330. }  
  331.  
  332. void one_wire_conversion_pulse(void) {
  333.         TRISCbits.TRISC1 = 0;
  334.         LATCbits.LATC1 = 1;          //For T conv we drive the DQ line high for 750ms (12bit)
  335.     __delay_us(250);                 // delay
  336.     __delay_us(250);                  
  337.         __delay_us(250);                  
  338.     TRISCbits.TRISC1 = 1;
  339.         LATCbits.LATC1 = 0;             //just in case this causes problems elsewhere                              
  340. }
  341.  
  342. int main(void) {
  343.  
  344.     init_io();
  345.  
  346.     // set up oscillator control register, using internal OSC at 16MHz.
  347.     OSCCONbits.IRCF = 0x07; //set OSCCON IRCF bits to select OSC frequency 16MHz
  348.     OSCCONbits.SCS = 0x02; //set the SCS bits to select internal oscillator block
  349.  
  350.     //RCONbits.IPEN = 0;          //dsiable priority levels
  351.  
  352.     INTCONbits.PEIE = 1;        // Enable peripheral interrupt
  353.     INTCONbits.GIE = 1;         // enable global interrupt
  354.  
  355.  
  356.     init_adc();                 //unused but AN4 is there if I need it
  357.     serial_init();
  358.  
  359.     uart_send ('x');
  360.  
  361.         LATAbits.LATA0 = 0; //this is just for debugging with an LA..
  362.         __delay_us(1);
  363.         LATAbits.LATA0 = 1; //also confirms oscillator setup is correct.. 1us width
  364.         __delay_us(1);
  365.         LATAbits.LATA0 = 0;
  366.  
  367.     while (1) {
  368.  
  369.         one_wire_reset();
  370.  
  371.         if (device_present) {
  372.             LATCbits.LATC2 = 1;             //this is a 1-wire device out there for debugging
  373.  
  374.             one_wire_tx_byte(0x55);
  375.  
  376.         }
  377.  
  378.  
  379.     }
  380.     return (EXIT_SUCCESS);
  381. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement