0

I'm working on a pic18f67k22, trying to get 5 DS18B20 temperature sensors to work. the first 4 will read temperatures perfectly, whichever sensor I give the value 4(or higher) will only return 255's when reading the temperature. This means the hardware is fine, we can also read every sensor in JAL, just not in C.

Me and my colleagues can not comprehend what could possibly cause this issue. For that reason I will apologize up front but this will be a code dump.

main.c:(main.h contains nothing)

/*
 * File:   main.c
 * Author: Wesley
 *
 * Created on September 6, 2022, 9:17 AM
 */

#include "fuses.h"

#include <stdbool.h>
#include <stdio.h>
#include <xc.h>

#include "clock.h"
#include "co2.h"
#include "delay.h"
#include "exti.h"
#include "i2c_drv.h"
#include "interrupt.h"
#include "LCDSerialTerminalMaster.h"
#include "onewire.h"
#include "pin.h"
#include "pwm.h"
#include "sim800.h"
#include "tempsensors.h"
#include "uart1.h"

uint8_t prevSec = 0;

void main(void)
{
    // disable comparators
    CM1CONbits.CON = 0;
    CM2CONbits.CON = 0;
    CM3CONbits.CON = 0;
    
    // disable analog input
    ADCON0bits.ADON = false;
    ANCON0 = 0;
    ANCON1 = 0;
    ANCON2 = 0;
    
    // turn 3v3 on to enable peripherals
    POWER_PIN_DIR = OUTPUT;
    POWER_PIN_OUT = LOW;
    
    INT_Init();
    UART1_Init();
    printf("_____START_____\r\n");
    
    I2C_Init();
    
    CLK_Init();
    LCD_Init();
    
    TEMP_Init();
    
    //SIM800_Init();//doesn't work, not receiving enough power consistently
    
    //needs to move to UI_Init
    CCP6CONbits.CCP6M   = 0b1100;       //PWM mode, single output for UI LEDs
    PWM_SetLed(255);
    
    printf("_____INIT DONE_____\r\n");
    
    while(1)
    {
        if(CLK_GetSec() != prevSec)
        {
            prevSec = CLK_GetSec();
            
            EXTI_Main(0);
            //SIM800_Main();//doesn't work, not receiving enough power consistently
            //CO2_Main();//all but scd30 get detected
            TEMP_Main();//doesn't work, last sensor(whichever gets highest value) always returns as not attached
            EXTI_Main(1);
            
            EXTI_Main(2);
            LCD_Write();
            
            EXTI_Main(3);
            
            EXTI_Main(4);
        }
    }
    
}
    

clock.c:(clock.h only contains prototypes)

/*
 * File:   clock.c
 * Author: Wesley
 *
 * Created on September 13, 2022, 2:10 PM
 */


#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <xc.h>

static uint8_t hour = 0;
static uint8_t min = 0;
static uint8_t sec = 0;
static volatile uint16_t ms = 0;

void CLK_Init(void)
{
    T3CONbits.TMR3CS = 0b00; // Source = Fosc/4
    T3CONbits.SOSCEN = 0b1;  // SOSC disabled
    T3CONbits.T3CKPS = 0b00; // Prescaler 1:1

    CCP4CONbits.CCP4M = 0b1011; // Compare Mode: Special Event Trigger, reset TMR3 on CCP4 match
    CCPTMRS1bits.C4TSEL = 0b01; // TMR3/TMR4

    // set compare value to 5000
    CCPR4L = 136;
    CCPR4H = 19;

    // Disable TMR3 interrupt.
    PIE2bits.TMR3IE = 0;

    // clear CCP4 interrupt.
    PIR4bits.CCP4IF = 0;

    // enable CCP4 interrupt.
    PIE4bits.CCP4IE = 1;
    IPR4bits.CCP4IP = 1;

    // Start the Timer by writing to TMRxON bit.
    T3CONbits.TMR3ON = 1;
}

void CLK_SetTime(uint8_t s, uint8_t m, uint8_t h)
{
    sec = s;
    min = m;
    hour = h;
}

void CLK_GetTime(char *buffer)
{
    sprintf(buffer, "%02hhu:%02hhu:%02hhu", hour, min, sec);
}

uint8_t CLK_GetSec(void)
{
    return sec;
}

uint16_t CLK_GetMs(void)
{
    return ms;
}

void CLK_ISR(void)
{   
    PIR4bits.CCP4IF = 0;
    ms++;
    if(ms == 1000)
    {
        ms = 0;
        sec++;
        if(sec == 60)
        {
            sec = 0;
            min++;
            if(min == 60)
            {
                min = 0;
                hour++;
                if(hour == 24)
                    hour = 0;
            }
        }
    }
}

delay.c(delay.h only contains prototypes)

/*
 * File:   delay.c
 * Author: Wesley
 *
 * Created on March 7, 2022, 1:08 PM
 */

#include "delay.h"

void Delay1us()
{
    //__asm("nop");//just the function call seems to be enough delay
}

void Delay2us()
{
    __asm(
    "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        );
}

void Delay3us()
{
    __asm(
    "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n");
}

void Delay4us()
{
    __asm(
    "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        );
}

void Delay5us()
{
    __asm(
    "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        );
}

void Delay6us()
{
    __asm(
    "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        );
}

void Delay7us()
{
    __asm(
    "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        );
}

void Delay8us()
{
    __asm(
    "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        );
}

void Delay9us()
{
    __asm(
    "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        "nop\n"
        );
}

void Delay10us(uint16_t amount)
{
    for (uint16_t i = 1; i < amount; i++)
    {
        Delay7us();
        __asm(
        "nop\n"
            "nop\n"
            );
    }
    Delay4us();
    __asm(
    "nop\n"
        );
}

void Delay1ms(uint16_t amount)
{
    for (uint16_t i = 1; i < amount; i++)
        Delay10us(99);
    Delay10us(98);
}

fuses.h:

/*
 * File:   config.h
 * Author: wesley
 *
 * Created on 6 september 2022, 10:11
 */

#ifndef FUSES_H
#define FUSES_H

// CONFIG1L
#pragma config SOSCSEL =    DIG // digital i/o on pin_c0 & pin_c1
#pragma config XINST =      OFF // Extended Instruction Set (Disabled)

// CONFIG1H
#pragma config FOSC =       HS2 //external oscillator

// CONFIG2L

// CONFIG2H
#pragma config WDTEN =      OFF // no watchdog

// CONFIG3L
#pragma config RTCOSC =     INTOSCREF // rtcc uses  internal oscillator

// CONFIG3H
#pragma config MCLRE =      OFF // reset externally

// CONFIG4L
#pragma config DEBUG =      OFF // no debugging

// CONFIG5L

// CONFIG5H

// CONFIG6L

// CONFIG6H

// CONFIG7L

// CONFIG7H



#include <xc.h>


#endif  /* FUSES_H */

interrupt.c:(interrupt.h only contains prototypes)

/*
 * File:   interrupt.c
 * Author: Wesley
 *
 * Created on September 6, 2022, 6:41 PM
 */

#include <stdbool.h>

#include "interrupt.h"

#include "clock.h"
//#include "i2c_drv.h"
#include "pin.h"
#include "uart1.h"

void INT_Init(void)
{
    // Enable Interrupt Priority Vectors
    IPEN = 1;

    // RCI - high priority
    UART2_RC_IP = 1;
    
    UART2_TX_IP = 0;

    MASTER_SYNC_IP = 1;
    
    INT_Toggle(true);
}

void INT_Toggle(bool toggle)
{
    INT_ToggleHigh(toggle);
    INT_ToggleLow(toggle);
}

void INT_ToggleHigh(bool toggle)
{
    INTCONbits.GIEH = toggle;
}

void INT_ToggleLow(bool toggle)
{
    INTCONbits.GIEL = toggle;
}

void __interrupt(high_priority) INT_InterruptManagerHigh(void)
{
    if(PIR4bits.CCP4IF)
        CLK_ISR();
    if(UART1_RC_IF)
        UART1_RC_ISR();
}

void __interrupt(low_priority) INT_InterruptManager(void)
{
    
}

onewire.c:(onewire.h only contains prototypes)

/*
 * File:   onewire.c
 * Author: Wesley
 *
 * Created on September 21, 2022, 4:57 PM
 */

#include <stdbool.h>

#include "delay.h"
#include "interrupt.h"
#include "tempsensors.h"
#include "pin.h"

//debug
#include "uart1.h"

static bool GetPin(TEMP_sensor_t sensor)
{
    switch(sensor)
    {
        case T1:
            return T1_IN;
        case T2:
            return T2_IN;
        case T3:
            return T3_IN;
        case T4:
            return T4_IN;
        case T5:
            return T5_IN;
        default://suppresses warning
            return false;
    }
}

static void SetDir(TEMP_sensor_t sensor, bool value)
{
    switch(sensor)
    {
        case T1:
            T1_DIR = value;
            break;
        case T2:
            T2_DIR = value;
            break;
        case T3:
            T3_DIR = value;
            break;
        case T4:
            T4_DIR = value;
            break;
        case T5:
            T5_DIR = value;
            break;
        default://suppresses warning
            break;
    }
}

static void SetLat(TEMP_sensor_t sensor, bool value)
{
    switch(sensor)
    {
        case T1:
            T1_OUT = value;
            break;
        case T2:
            T2_OUT = value;
            break;
        case T3:
            T3_OUT = value;
            break;
        case T4:
            T4_OUT = value;
            break;
        case T5:
            T5_OUT = value;
            break;
        default://suppresses warning
            break;
    }
}

static void SetPin(TEMP_sensor_t sensor, bool value)
{
    switch(sensor)
    {
        case T1:
            T1_IN = value;
            break;
        case T2:
            T2_IN = value;
            break;
        case T3:
            T3_IN = value;
            break;
        case T4:
            T4_IN = value;
            break;
        case T5:
            T5_IN = value;
            break;
        default://suppresses warning
            break;
    }
}

void OW_WriteBit(TEMP_sensor_t sensor , bool data)
{
    INT_Toggle(false);
    SetLat(sensor, LOW);
    SetDir(sensor, OUTPUT);
    Delay10us(1);
    if(data)
        SetDir(sensor, INPUT);
    Delay10us(8);
    SetDir(sensor, INPUT);
    Delay10us(1);
    INT_Toggle(true);
}

void OW_ReadBit(TEMP_sensor_t sensor, uint8_t *output)
{
    INT_Toggle(false);
    SetLat(sensor, LOW);
    SetDir(sensor, OUTPUT);
    Delay10us(1); 
    SetDir(sensor, INPUT);
    Delay10us(1);
    *output = GetPin(sensor);
    Delay10us(7);
    INT_Toggle(true);
}

void OW_WriteByte(TEMP_sensor_t sensor, uint8_t data)
{
    for(uint8_t i = 0; i < 8; i++)
    {
        OW_WriteBit(sensor, data & 1);
        data >>= 1;
    }
    SetLat(sensor, HIGH);
    SetDir(sensor, OUTPUT);
}

void OW_ReadByte(TEMP_sensor_t sensor, uint8_t *output)
{
    uint8_t b;//bit
    for(uint8_t i = 0; i < 8; i++)
    {
        *output >>= 1;
        OW_ReadBit(sensor, &b);
        *output += b << 7;
    }
    SetLat(sensor, HIGH);
    SetDir(sensor, OUTPUT);
}

void OW_Reset(TEMP_sensor_t sensor)
{
    SetLat(sensor, LOW);
    SetDir(sensor, OUTPUT);
    Delay10us(70);
    SetDir(sensor, INPUT);
    Delay10us(70);
}

pin.h(pin.c is nonexistent)

/* 
 * File:   pin.h
 * Author: Wesley
 *
 * Created on September 6, 2022, 1:00 PM
 *
 *
 *
 * PIC18F67K22 pin connections
 * nr    pin                 function    signal name
 * 1     RE1/!WR/P2C         io          MUX_A_DIR      serial multiplexer address 2
 * 2     RE0/!RD/P2D         io          MUX_B_DIR      serial multiplexer address 1
 * 3     RG0/ECCP3/P3A       io          SPARE7         to spare connector
 * 4     RG1/TX2/CK2         io          WF_RX          wifi UART receive
 * 5     RG2/RX2/DT2         io          WF_TX          wifi UART transmit
 * 6     RG3/CCP4/P3D        io          BUZZER         buzzer via CCP4
 * 7     !MCLR               in          !MCLR          reset
 * 8     RG4/CCP5/T7CKI      io          RPM_FAN2       fan RPM VIA TMR7
 * 9     VSS                 pwr         GND            GND
 * 10    VDDCORE/VCAP        pwr         VDD_CORE       to capacitor
 * 11    RF7/!SS1            io          SEND/!REC      send_rec to ADM3493, RS485
 * 12    RF6/AN11            io          LEDS           green/red LEDs
 * 13    RF5/AN10/CVREF      io          SPARE5         to spare connector
 * 14    RF4/AN9             io          SPARE3         to spare connector
 * 15    RF3/AN8             io          SPARE4         to spare connector
 * 16    RF2/AN7/C1OUT       io          SPARE6         to spare connector
 * 17    RF1/AN6/C2OUT       io          SPARE9         to spare connector
 * 18    ENVREG              in          +5V            +5V
 * 19    AVDD                pwr         +5V            +5V
 * 20    AVSS                pwr         GND            GND
 * 21    RA3/AN3/VREF+       io          SPARE8         to spare connector
 * 22    RA2/AN2/VREF-       io          DS18B20_T5     DS18B20 sensor 5, aka T2A
 * 23    RA1/AN1             io          DS18B20_T4     DS18B20 sensor 4
 * 24    RA0/AN0             io          SPARE10        to spare connector
 * 25    VSS                 pwr         GND            GND
 * 26    VDD                 pwr         +5V            +5V
 * 27    RA5/AN4             io          DS18B20_T1     DS18B20 sensor 1
 * 28    RA4/T0CK            io          DS18B20_T3     DS18B20 sensor 3
 * 29    RC1/T1OSI/ECCP2/P2A io          PWM_FAN1       PWM fan 1 via ECCP2
 * 30    RC0/T1OSO/T13CKI    io          DS18B20_T2     DS18B20 sensor 2
 * 31    RC6/TX1/CK1         io          MUX_RX         mux UART transmit
 * 32    RC7/RX1/DT1         io          MUX_TX         mux UART receive
 * 33    RC2/ECCP1/P1A       io          PWM_FAN2       PWM fan 2 via ECCP1
 * 34    RC3/SCK1/SCL1       io          SCL            I2C
 * 35    RC4/SDI1/SDA1       io          SDA            I2C
 * 36    RC5/SDO1            io          COUPLE_CHECK   resistance measurement thermocouple
 * 37    RB7/KBI2/PGD        io          PGD            ICSP
 * 38    VDD                 pwr         +5V            +5V
 * 39    OSC1/CLKI           in          OSC1           20 Mhz crystal
 * 40    OSC2/CLKO           out         OSC2           20 Mhz crystal
 * 41    VSS                 pwr         GND            GND
 * 42    RB6/KBI2/PGC        io          PGC            ICSP
 * 43    RB5/KBI1            io          STERM          LCD and keyboard
 * 44    RB4/KBI0            io          HEAT_          to heater triac optocoupler
 * 45    RB3/INT3            io          RELAY          powers heater
 * 46    RB2/INT2            io          ZERO_CROSS     230V AC zero cross timing
 * 47    RB1/INT1            io          TRIAC_CHECK    heater voltage
 * 48    RB0/INT0/FLT0       io          RF_DATA        incoming 433 Mhz remote control
 * 49    RD7/PSP7/!SS2       io          UI19           auto button
 * 50    RD6/PSP6/SCK2/SCL2  io          UI_SCK         UI LEDs clock
 * 51    RD5/PSP5/SDI2/SDA2  io          SPARE11        not used
 * 52    RD4/PSP4/SDO2       io          UI_DATA        UI LEDs data
 * 53    RD3/PSP3            io          SPARE12        not used
 * 54    RD2/PSP2            io          SPARE14        not used
 * 55    RD1/PSP1/T5CKI      io          RPM_FAN1       fan RPM VIA TMR5
 * 56    VSS                 pwr         GND            GND
 * 57    VDD                 pwr         +5V            +5V
 * 58    RD0/PSP0            io          !POWER_SENSORS MAX893 sensor power cycle
 * 59    RE7/ECCP2/P2A       io          !FAULT         MAX893 overcurrent
 * 60    RE6/P1B             io          UI_PWM         UI LEDs brightness via CCP6
 * 61    RE5/P1C             io          SIM800_POW     SIM800 power cycle
 * 62    RE4/P3B             io          WF_RESET       ESP32 AP mode
 * 63    RE3/P3C             io          UI5            UI flowmin button
 * 64    RE2/!CS/P2B         io          UI3            UI flowplus button
 */

#ifndef PIN_H
#define PIN_H

#include <xc.h>

#define OUTPUT          0
#define INPUT           1

#define LOW             0
#define HIGH            1

//FAN
#define FAN1_IN         PORTDbits.RD1
#define FAN1_DIR        TRISDbits.TRISD1
#define FAN1_PWM        CCPR2L
#define FAN1_PWM_IN     PORTCbits.RC1
#define FAN1_PWM_OUT    LATCbits.LC1
#define FAN1_PWM_DIR    TRISCbits.TRISC1
#define FAN2_IN         PORTGbits.RG4
#define FAN2_DIR        TRISGbits.TRISG4
#define FAN2_PWM        CCPR1L
#define FAN2_PWM_IN     PORTCbits.RC2
#define FAN2_PWM_OUT    LATCbits.LC2
#define FAN2_PWM_DIR    TRISCbits.TRISC2

//INTERRUPT
#define IPEN            RCONbits.IPEN
#define MASTER_SYNC_IP  IPR1bits.SSP1IP
#define RTC_IF          PIR3bits.RTCCIF
#define RTC_IP          IPR3bits.RTCCIP
#define UART2_RC_IF     PIR3bits.RC2IF
#define UART2_RC_IP     IPR3bits.TX2IP
#define UART2_TX_IF     PIR3bits.RC2IF
#define UART2_TX_IP     IPR3bits.TX2IP

//LCD
#define LCD_PIN_DIR     TRISBbits.TRISB5
#define LCD_PIN_OUT     LATBbits.LB5
#define LCD_PIN_IN      PORTBbits.RB5

//MAIN
#define LED_DIM         CCPR6L
    //ICSP
    #define PGC         PORTBbits.RB6
    #define PGC_DIR     TRISBbits.TRISB6
    #define PGD         PORTBbits.RB7
    #define PGD_DIR     TRISBbits.TRISB7

//ONEWIRE
#define T1_IN           PORTAbits.RA5
#define T1_OUT          LATAbits.LA5
#define T1_DIR          TRISAbits.TRISA5
#define T2_IN           PORTCbits.RC0
#define T2_OUT          LATCbits.LC0
#define T2_DIR          TRISCbits.TRISC0
#define T3_IN           PORTAbits.RA4
#define T3_OUT          LATAbits.LA4
#define T3_DIR          TRISAbits.TRISA4
#define T4_IN           PORTAbits.RA1
#define T4_OUT          LATAbits.LA1
#define T4_DIR          TRISAbits.TRISA1
#define T5_IN           PORTAbits.RA2
#define T5_OUT          LATAbits.LA2
#define T5_DIR          TRISAbits.TRISA2

//PIEZO
#define BEEP_IN         PORTGbits.RG3
#define BEEP_DIR        TRISGbits.TRISG3

//POWER
#define POWER_IN        PORTDbits.RD0
#define POWER_PIN_DIR   TRISDbits.TRISD0
#define POWER_PIN_OUT   LATDbits.LD0

//RF
#define RF_IN           PORTBbits.RB0
#define RF_DIR          TRISBbits.TRISB0

//RTC
#define RTC_IE          PIE3bits.RTCCIE

//SIM
#define SIM_POWER       PORTEbits.RE5
#define SIM_POWER_OUT   LATEbits.LE5
#define SIM_POWER_DIR   TRISEbits.TRISE5

//TEMP

//TCPL
#define TCPL_CHECK      PORTCbits.RC5
#define TCPL_CHECK_DIR  TRISCbits.TRISC5

//UART1
#define MUX_A           LATEbits.LE1
#define MUX_A_DIR       TRISEbits.TRISE1
#define MUX_B           LATEbits.LE0
#define MUX_B_DIR       TRISEbits.TRISE0
#define MUX_RC_DIR      TRISCbits.TRISC6
#define MUX_TX_DIR      TRISCbits.TRISC7

#define SEND_REC        LATFbits.LF7
#define SEND_REC_DIR    TRISFbits.TRISF7

#define UART1_RC_IE     PIE1bits.RC1IE
#define UART1_RC_IF     PIR1bits.RC1IF
#define UART1_RC_IP     IPR1bits.RC1IP
#define UART1_TX_IF     PIR1bits.TX1IF
#define UART1_TX_IP     IPR1bits.TX1IP

//UART2
#define WF_RESET        PORTEbits.RE4
#define WF_RESET_DIR    TRISEbits.TRISE4
#define WF_RC           PORTGbits.RG1
#define WF_RC_DIR       TRISGbits.TRISG1
#define WF_TX           PORTGbits.RG2
#define WF_TX_DIR       TRISGbits.TRISG2
#define UART2_RC_IE     PIE3bits.RC2IE
#define UART2_TX_IDLE   TXSTA2bits.TRMT

#endif  /* PIN_H */

tempsensors.c:

    /*
 * File:   tempsensors.c
 * Author: Wesley
 *
 * Created on September 21, 2022, 4:40 PM
 */

#include <stdbool.h>
#include <stdint.h>

#include "onewire.h"
#include "pin.h"
#include "tempsensors.h"

//debug
#include "uart1.h"

static uint8_t scratchpad[TEMP_SENSOR_AMOUNT][9];
static int16_t value[TEMP_SENSOR_AMOUNT];

static bool reading = true;

//static uint8_t crc8(uint8_t* data, uint8_t len)
//{
//    uint8_t crc = 0;
//    while (len--)
//    {
//        uint8_t inbyte = *data++;
//        for (uint8_t i = 8; i; i--)
//        {
//            uint8_t mix = (crc ^ inbyte) & 0x01;
//            crc >>= 1;
//            if (mix) crc ^= 0x8C;
//            inbyte >>= 1;
//        }
//    }
//    return crc;
//}

//BytesToRead == 8 = read ROM ID
//BytesToRead == 9 = read hw scratchpad
static void Read(uint8_t sensor, uint8_t BytesToRead)
{
    // read a number of bytes and calculate the CRC value of
    // the complete group  
    for(uint8_t i = 0; i < BytesToRead; i++)
        OW_ReadByte(sensor, &scratchpad[sensor][i]);
    
    if(BytesToRead == 9 && scratchpad[sensor][4] == 0xFF && scratchpad[sensor][5] == 0xFF && 
       scratchpad[sensor][6] == 0xFF && scratchpad[sensor][7] == 0xFF && scratchpad[sensor][8] == 0xFF)
    {
        printf("T%hhu NOT ATTACHED\r\n", sensor + 1);
        // probe is not present, all read to 0xFF
        // set the CRC value to false, and reset temp with error scale 99°c
        scratchpad[sensor][0] = 198;
    }
}

static void SkipRom(uint8_t sensor)
{
    OW_Reset(sensor);
    OW_WriteByte(sensor, 0xCC);
}

//converts sensor temp to readable temp
static void Convert(uint8_t sensor)
{
    SkipRom(sensor);
    OW_WriteByte(sensor, 0x44); // init temp conversion cmd
}

static void ReadTemp(uint8_t sensor)
{
    SkipRom(sensor);
    OW_WriteByte(sensor, 0xBE);
    Read(sensor, 9);
}

void TEMP_Init(void)
{
    T1_OUT = LOW;
    T1_DIR = INPUT;
    T2_OUT = LOW;
    T2_DIR = INPUT;
    T3_OUT = LOW;
    T3_DIR = INPUT;
    T4_OUT = LOW;
    T4_DIR = INPUT;
    T5_OUT = LOW;
    T5_DIR = INPUT;
}

void TEMP_Main(void) 
{
    if(reading)
    {
        for(uint8_t sensor = 0; sensor < TEMP_SENSOR_AMOUNT; sensor++)
        {
            ReadTemp(sensor);
            value[sensor] = (((int16_t)(scratchpad[sensor][1] << 8) + scratchpad[sensor][0]) * 10) >> 4;
            printf("T%u:%hu\t%hu\r\n", sensor + 1, scratchpad[sensor][1], scratchpad[sensor][0]);
            printf("T%u:%hu\r\n", sensor + 1, value[sensor]);
        }
    }
    else
    {
        for(uint8_t sensor = 0; sensor < TEMP_SENSOR_AMOUNT; sensor++)
            Convert(sensor);
    }
    reading = !reading;
}

int16_t TEMP_GetValue(uint8_t sensor)
{
    return value[sensor];
}

uart1.c:(uart1.h only contains prototypes)

/*
 * File:   uart1.c
 * Author: Wesley
 *
 * Created on September 6, 2022, 3:43 PM
 */

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <xc.h>

#include "uart1.h"

#include "delay.h"
#include "pin.h"

UART1_direction_t dir;

uint8_t *UART1_simBuf;
uint8_t UART1_simPtr = 0;

//debug 
char c;

static void SetDirection(UART1_direction_t direction)
{
    dir = direction;
    MUX_A = (dir & 1);
    MUX_B = (dir & 2) != 0;
    Delay10us(2);
}

static void WriteChar(char data, uint8_t len)
{
    while(!UART1_TX_IF);
    TXREG1 = data;
}

static void WriteString(char *data, uint8_t len)
{
    for(uint8_t i = 0; i < len; i++)
    {
        while(!UART1_TX_IF);
        TXREG1 = data[i];
    }
}

void UART1_Init(void) 
{
    MUX_RC_DIR = OUTPUT;
    MUX_TX_DIR = INPUT;
    MUX_A_DIR = OUTPUT;
    MUX_B_DIR = OUTPUT;
    
    //according to JAL
    BAUDCON1 = 0b01001000;// RCIDL, BRG16
    TXSTA1 = 0b00100100;// TXEN, BRGH
    RCSTA1 = 0b10010000; //SPEN, CREN
    //SPBRG1 = 42; //115200
    SPBRG1 = 0x08;// BAUD 9600
    SPBRGH1 = 0x02; 
    SEND_REC_DIR = OUTPUT;
    
    UART1_RC_IE = true;
    UART1_RC_IP = HIGH;
    UART1_TX_IP = LOW;
    
    SetDirection(UART1_SIM);
}

void putch(char data)
{
    SetDirection(UART1_FTDI);
    WriteChar(data, 1);
}

void UART1_WriteSim(char *data)
{
    SetDirection(UART1_SIM);
    WriteString(data, (uint8_t)(strchr(data, '\0') - data));
}

void UART1_RC_ISR(void)
{
    if(RCSTA1bits.OERR)//if overflow, restart
    {
        RCSTA1bits.CREN = 0;
        RCSTA1bits.CREN = 1;
        return;
    }
    
    c = RCREG1;
    switch(dir)
    {
        case UART1_SIM:
//            if(UART1_simPtr < SIM_BUFFER_SIZE)
//                UART1_simBuf[UART1_simPtr++] = c;
            break;
        case UART1_RS485:
            break;
        case UART1_FTDI:
            break;
        case UART1_DUST_D1:
            break;
    }
}

char UART1_GetLast(void)
{
    return c;
}

Again sorry for dumping all code but we are kind of desperate. If there are any questions remaing, please ask and I will try to answer to the best of my ability.

  • What is TEMP_SENSOR_AMOUNT? – stark Sep 29 '22 at 12:39
  • `SetPin` should be writing to LATs rather than PORTs – stark Sep 29 '22 at 12:55
  • @stark my apologies, i said tempsensors.h only contained prototypes, this was false. TEMP_SENSOR_AMOUNT is the final value in the enum with my temp sensors, will edit accordingly. We have have changed SetPin to a new SetLat method, no difference. T5(or whichever goes last) only returns 255. – Wesley Kienhuis Sep 29 '22 at 13:56
  • I would have expected TEMP_SENSOR_AMOUNT to be 1 past the final value in the enum. Are you sure it evaluates to 5 or more, not 4? – DavidHoadley Oct 06 '22 at 05:59

1 Answers1

0

Not sure if it's the cause of this problem, but you do have one bug here:
(int16_t)(scratchpad[sensor][1] << 8).

Since you are using an 8-bitter, the uint8_t operand scratchpad[sensor][1] will get implicitly promoted to int, which is 16 bits (see Implicit type promotion rules). After which you potentially shift data into the sign bit, leading to undefined behavior. And later upon right-shifting, you could get similar problems because of that.

The cast to int16_t is pointless - the result will already be in that type thanks to the implicit promotion. But you need to ensure that bit shift always happen on an operand which is type uint16_t! Not uint8_t, not int16_t. Contrary to popular belief, 8-bitters are not that trivial to program in C. The 16 bit int type means you need to know all implicit type promotion rules well.

Corrected code where I'm doing splitting the messy "one-liner" into several, to improve readability:

uint16_t tmp = (uint16_t)scratchpad[sensor][1] << 8;
tmp += scratchpad[sensor][0];
tmp *= 10;
value[sensor] = (int16_t) (tmp >> 4);
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Thanks for your reply. Converting the readout to an actual temperature is not the problem. whichever sensor is read last (reading all at the same time or waiting a second between each sensor) it will only return 255 bytes. – Wesley Kienhuis Oct 04 '22 at 07:04
  • @WesleyKienhuis Regardless, you need to fix this obvious bug. – Lundin Oct 04 '22 at 07:30