Advertisement
chasxmd

1-wire with T-Sense and PIC 18F14K22

Jan 2nd, 2015
501
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.54 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.     int     device_present;             // 1 = 1-wire device on 1-wire bus
  85.     int     i, x, y, int_temp, an4_value;               //
  86.     long int    decm;
  87.     int     itxdata, txdata;            //int RS232 tx data
  88.     char    rxbuff[10], z[1], buf[4];                 //buffer for T-sense 1-wire device
  89.     float    temperature, f, d;
  90.     volatile unsigned int uart_data;    // use 'volatile' qualifer as this is changed in ISR
  91.  
  92. /*
  93.  *  Functions
  94.  */
  95.  
  96.     void interrupt ISR() {
  97.  
  98.     if (PIR1bits.RCIF)          // see if interrupt caused by incoming data .. unused currently
  99.     {
  100.         uart_data = RCREG;     // read the incoming data
  101.         PIR1bits.RCIF = 0;      // clear interrupt flag
  102.                                 //
  103.     }
  104.     // I left this timer interrupt if I needed it later. This is unused.
  105.     if (PIR1bits.TMR1IF)
  106.     {
  107.         //T1CONbits.TMR1ON = 0;
  108.         PIR1bits.TMR1IF = 0;
  109.         //T1CONbits.TMR1ON = 1;
  110.  
  111.     }
  112. }
  113.  
  114.  
  115.      void __delay_10ms(unsigned char n)     //__delay functions built-in can't be used for much at this speed... so!
  116.  {
  117.      while (n-- != 0) {
  118.          __delay_ms(10);
  119.      }
  120.  }
  121.  
  122.  
  123. void uart_send (unsigned int mydata_byte) {      //bytes
  124.  
  125.     while(!TXSTAbits.TRMT);    // make sure buffer full bit is high before transmitting
  126.     TXREG = mydata_byte;       // transmit data
  127. }
  128.  
  129. void write_uart(const char *txt)                //strings
  130. {
  131.                                 //this send a string to the TX buffer
  132.                                 //one character at a time
  133.        while(*txt)
  134.        uart_send(*txt++);
  135. }
  136.  
  137. //This code if from Microchip but is unused currently.
  138. void uart_send_hex_ascii(unsigned char display_data)
  139. {
  140.  
  141.     //unsigned char temp;
  142.     //temp = ((display_data & 0xF0)>>4);
  143.     //if (temp <= 0x09)
  144.     //  Putchar(temp+'0');
  145.     //else
  146.     //  Putchar(temp+'0'+0x07);
  147.         //
  148.     //temp = display_data & 0x0F;
  149.     //if (temp <= 0x09)
  150.     //  Putchar(temp+'0');
  151.     //else
  152.     //  Putchar(temp+'0'+0x07);
  153.  
  154.     //Putchar('\r');
  155.     //Putchar('\n');
  156. }
  157.  
  158. void serial_init(void)
  159. {
  160.  
  161.     // calculate values of SPBRGL and SPBRGH based on the desired baud rate
  162.     //
  163.     // For 8 bit Async mode with BRGH=0: Desired Baud rate = Fosc/64([SPBRGH:SPBRGL]+1)
  164.     // For 8 bit Async mode with BRGH=1: Desired Baud rate = Fosc/16([SPBRGH:SPBRGL]+1)
  165.  
  166.  
  167.  
  168.     TXSTAbits.BRGH=1;       // select low speed Baud Rate (see baud rate calcs below)
  169.     TXSTAbits.TX9=0;        // select 8 data bits
  170.     TXSTAbits.TXEN=1;     // enable transmit
  171.     BAUDCONbits.BRG16=0;
  172.  
  173.     RCSTAbits.SPEN=1;       // serial port is enabled
  174.     RCSTAbits.RX9=0;        // select 8 data bits
  175.     RCSTAbits.CREN=1;       // receive enabled
  176.  
  177.  
  178.     SPBRG=25;               //38,400bps-ish
  179.                             //BRG16=0, 7=31.25k, 25=9.615k
  180.  
  181.     PIR1bits.RCIF=0;        // make sure receive interrupt flag is clear
  182.     PIE1bits.RCIE=1;        // enable UART Receive interrupt
  183.  
  184.  
  185.          __delay_ms(10);        // give time for voltage levels on board to settle
  186.  
  187. }
  188.  
  189.  
  190. void init_io(void) {
  191.     ANSEL = 0x00;        
  192.     ANSELH = 0x00;
  193.  
  194.     TRISAbits.TRISA0 = 0; // output
  195.     TRISAbits.TRISA1 = 0; // output
  196.     TRISAbits.TRISA2 = 0; // output
  197.     TRISAbits.TRISA4 = 0; // output
  198.     TRISAbits.TRISA5 = 0; // output
  199.  
  200.  
  201.  
  202.     TRISBbits.TRISB4 = 0; // output
  203.     TRISBbits.TRISB5 = 1; // input (RX UART)
  204.     TRISBbits.TRISB6 = 0; // output
  205.     TRISBbits.TRISB7 = 0; // output (TX UART)
  206.  
  207.     LATC = 0x00;
  208.  
  209.     TRISCbits.TRISC0 = 1; // AN4
  210.     TRISCbits.TRISC1 = 1; // 1-wire data
  211.     TRISCbits.TRISC2 = 0; //
  212.     TRISCbits.TRISC3 = 0; //
  213.     TRISCbits.TRISC4 = 0; //
  214.     TRISCbits.TRISC5 = 0; // output
  215.     TRISCbits.TRISC6 = 1; // input
  216.     TRISCbits.TRISC7 = 1; // input
  217.  
  218. }
  219.  
  220.  
  221. void init_adc (void)
  222. {
  223.     ANSELbits.ANSEL4=1;         //PORTC.0
  224.     ADCON2bits.ADCS = 0x02;     //Fosc/32
  225.     ADCON2bits.ADFM=0;          //left oriented
  226.     ADCON1=0x00;
  227. }
  228.  
  229. void read_adc (void)
  230. {
  231.     ADCON0bits.CHS0 = 0;        // AD4
  232.     ADCON0bits.CHS1 = 0;
  233.     ADCON0bits.CHS2 = 1;
  234.     ADCON0bits.CHS3 = 0;
  235.     ADCON0bits.ADON = 1;        // A/D ON
  236.     __delay_us(5);
  237.  
  238.     ADCON0bits.GO   = 1;        // ..GO!
  239.  
  240.     __delay_us(5);
  241.  
  242.         while (ADCON0bits.GO) continue;              //wait for conversion
  243.         an4_value = ADRESH;                          //AN4 value
  244. }
  245.  
  246. void one_wire_reset(void) {
  247.     device_present = 0x00;
  248.     TRISCbits.TRISC1 = 0;
  249.     LATCbits.LATC1 = 0;
  250.     __delay_us(240);        //delay 480 us
  251.     __delay_us(240);
  252.     TRISCbits.TRISC1 = 1;
  253.     __delay_us(70);
  254.     if (!PORTCbits.RC1) {
  255.             device_present = 0x01;
  256.     }
  257.     __delay_us(205);        //delay 410 us
  258.     __delay_us(205);
  259. }
  260.  
  261. //this looks a lot like the Microchip code, it was not I just happened to be on the right track.
  262. void one_wire_tx_bit(unsigned char txbit) {         // write a bit
  263.     if (txbit) {
  264.     TRISCbits.TRISC1 = 0;
  265.     LATCbits.LATC1 = 0;
  266.     __delay_us(6);    
  267.     TRISCbits.TRISC1 = 1;
  268.     __delay_us(64);      
  269.     }
  270.     else {      
  271.     TRISCbits.TRISC1 = 0;
  272.     LATCbits.LATC1 = 0;
  273.     __delay_us(60);    
  274.     TRISCbits.TRISC1 = 1;
  275.     __delay_us(10);    
  276.     }
  277. }
  278.  
  279. //from Microchip AN1199 code, renamed and slightly modified to match my software
  280. /**********************************************************************
  281. * Function:        void OW_write_byte (unsigned char write_data)
  282. * PreCondition:    None
  283. * Input:           Send byte to 1-wire slave device
  284. * Output:          None
  285. * Overview:        This function used to transmit a complete byte to slave device.
  286. *                  
  287. ***********************************************************************/
  288. void one_wire_tx_byte (unsigned char write_data)
  289. {
  290.     unsigned char loop;
  291.    
  292.     for (loop = 0; loop < 8; loop++)
  293.     {
  294.         one_wire_tx_bit(write_data & 0x01);     //Sending LS-bit first
  295.         write_data >>= 1;                   // shift the data byte for the next bit to send
  296.     }  
  297. }  
  298.  
  299.  
  300. //from Microchip AN1199 code: I gathered the essence of this but seeing as I am not using most of the AN1199 code
  301. //and this would not work with XC8 I had to re-write this.
  302. /**********************************************************************
  303. * Function:        unsigned char OW_read_bit (void)
  304. * PreCondition:    None
  305. * Input:           None
  306. * Output:          Return the status of the OW PIN
  307. * Overview:        This function used to read a single bit from the slave device.
  308. *                  
  309. ***********************************************************************/
  310.  
  311. unsigned char one_wire_rx_bit (void)
  312. {
  313.     unsigned char read_data;
  314.         read_data = 0x00;
  315.     //reading a bit
  316.     TRISCbits.TRISC1 = 0;
  317.         LATCbits.LATC1 = 0;                         // Drive the bus low
  318.     __delay_us(6);                      // delay 6 microsecond (us)
  319.     TRISCbits.TRISC1 = 1;                       // Release the bus
  320.     __delay_us(9);                      // delay 9 microsecond (us)
  321.  
  322.         if (PORTCbits.RC1) {                                    //read 1 or 0
  323.             read_data = 0x01;
  324.         }
  325.  
  326.     __delay_us(55);                     // delay 55 microsecond (us)   
  327.     return read_data;
  328. }
  329.  
  330.  
  331. /**********************************************************************
  332. * Function:        unsigned char OW_read_byte (void)
  333. * PreCondition:    None
  334. * Input:           None
  335. * Output:          Return the read byte from slave device
  336. * Overview:        This function used to read a complete byte from the slave device.
  337. *                  
  338. ***********************************************************************/
  339.  
  340. unsigned char one_wire_rx_byte (void)
  341. {
  342.     unsigned char loop, result=0;
  343.    
  344.     for (loop = 0; loop < 8; loop++)                // here we are reading 8 bits (1 byte)
  345.     {
  346.        
  347.         result >>= 1;               // shift the result to get it ready for the next bit to receive
  348.         if (one_wire_rx_bit())
  349.         result |= 0x80;             // if result is one, then set MS-bit
  350.     }
  351.     return result;                 
  352. }  
  353.  
  354. void one_wire_conversion_pulse(void) {
  355.         TRISCbits.TRISC1 = 0;
  356.         LATCbits.LATC1 = 1;          //For T conv we drive the DQ line high for 750ms (12bit)
  357.     __delay_us(250);                 // delay
  358.     __delay_us(250);                  
  359.         __delay_us(250);                  
  360.     TRISCbits.TRISC1 = 1;
  361.         LATCbits.LATC1 = 0;             //just in case this causes problems elsewhere                              
  362. }
  363.  
  364. int main(void) {
  365.  
  366.     init_io();
  367.  
  368.     // set up oscillator control register, using internal OSC at 16MHz.
  369.     OSCCONbits.IRCF = 0x07; //set OSCCON IRCF bits to select OSC frequency 16MHz
  370.     OSCCONbits.SCS = 0x02; //set the SCS bits to select internal oscillator block
  371.  
  372.     //RCONbits.IPEN = 0;          //dsiable priority levels
  373.  
  374.     INTCONbits.PEIE = 1;        // Enable peripheral interrupt
  375.     INTCONbits.GIE = 1;         // enable global interrupt
  376.  
  377.  
  378.     init_adc();                 //unused but AN4 is there if I need it
  379.     serial_init();
  380.  
  381.     uart_send ('x');
  382.  
  383.         LATAbits.LATA0 = 0; //this is just for debugging with an LA..
  384.         __delay_us(1);
  385.         LATAbits.LATA0 = 1; //also confirms oscillator setup is correct.. 1us width
  386.         __delay_us(1);
  387.         LATAbits.LATA0 = 0;
  388.  
  389.     while (1) {
  390.  
  391.         one_wire_reset();
  392.  
  393.         if (device_present) {
  394.             LATCbits.LATC2 = 1;             //this is a 1-wire device out there for debugging
  395.  
  396.             one_wire_tx_byte(0xCC);         //skip-rom (similar to a broadcast)
  397.  
  398.             one_wire_tx_byte(0x44);         //do a temp conversion
  399.  
  400.             one_wire_conversion_pulse();    // hold DQ line high for 750ms
  401.  
  402.             one_wire_reset();
  403.  
  404.             //add additional check here later
  405.  
  406.             one_wire_tx_byte(0xCC);         //skip-rom (similar to a broadcast)
  407.  
  408.             one_wire_tx_byte(0xBE);         //read scratch pad
  409.  
  410.             for(i = 0; i<9; i++)            //reading all 9 bytes on the T-Sense
  411.         rxbuff[i] = one_wire_rx_byte();
  412.             // T-Sense
  413.             //  Byte 0 LSB of Temp
  414.             //  Byte 1 MSB of Temp and sign
  415.  
  416.             // LSB
  417.             //  2^3 2^2 2^1 2^0 2^-1 2^-2 2^-3 s^-4
  418.             // MSB
  419.             // S S S S S 2^6 2^5 2 ^ 4
  420.  
  421.  
  422.  
  423.             temperature = 0;
  424.             f = 0.0625;
  425.  
  426.             //z[0] = rxbuff[1];
  427.             //x = atoi(z);
  428.             x = rxbuff[1];
  429.  
  430.             if (x & 0b10000000) {
  431.                 uart_send('-');
  432.             } else {
  433.                 uart_send('+');
  434.             }
  435.            
  436.             x = x & 0b00000111;
  437.  
  438.             int_temp = 0;
  439.  
  440.             int_temp = rxbuff[0];
  441.  
  442.             if (x & 0b00000001)
  443.                 int_temp = int_temp + 0x100;
  444.             if (x & 0b00000010)
  445.                 int_temp = int_temp + 0x200;
  446.             if (x & 0b00000100)
  447.                 int_temp = int_temp + 0x400;
  448.  
  449.             temperature = int_temp * f;
  450.            
  451.             int_temp = temperature;
  452.  
  453.             itoa(z, int_temp, 10);
  454.             write_uart(z);
  455.             uart_send('.');
  456.  
  457.             d = temperature - int_temp;
  458.  
  459.             decm = d * 1000;
  460.  
  461.             //page 374 of XC8 user guide
  462.             ltoa(buf,decm,10);  //long conversion to buffer
  463.             y=strlen(buf);  //uh, adding leading zeros..
  464.             y=3-y;      //probably a better way of doing thing
  465.             while (y)       //first figure out how many zeros
  466.             {
  467.                 uart_send('0');  //missed 3-string length
  468.                 y=y-1;  //then send them until done
  469.             }  
  470.             write_uart (buf);
  471.        
  472.             uart_send(0x0A);        //LF
  473.             uart_send(0x0D);        //CR
  474.  
  475.             //temperature   float temperature
  476.             //int_temp      interger value of temperature
  477.  
  478.             __delay_10ms(254);
  479.         }
  480.  
  481.     }
  482.     return (EXIT_SUCCESS);
  483. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement