/* * File: main.c * Author: clement * * Created on July 14, 2025, 3:54 PM */ #include #include #include // Configuration bits #pragma config FOSC = INTOSC // Oscillator Selection bits (INTOSC oscillator: I/O function on CLKIN pin) #pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled) #pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is digital input) #pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled) #pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled) #pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin) #pragma config LVP = OFF #pragma config DEBUG = ON #pragma config PLLEN = 0 // Pins define #define DHT22_PIN_DIR TRISAbits.TRISA4 #define DHT22_DATA PORTAbits.RA4 #define CTRL_1 PORTAbits.RA5 #define CTRL_2 PORTAbits.RA2 // Clock frequency (used for __delay_xx) #define _XTAL_FREQ 8000000 // Utils macro for waiting a pin state for DHT22_DATA, returning 1 if timed out. #define waitDHTOrRet(up) TMR0 = 0; while(DHT22_DATA != (up)){ if(TMR0 > 240) return 1; } uint8_t dhtBytes[5]; // 2 first bytes: humidity, 2 following: temperature, 5th: checksum // Reads the DHT, returns 0 if error int readDHT() { // Empty old payload for(uint8_t i = 0; i < 5; i++){ dhtBytes[i] = 0; } // Wait for an old payload eventually aborted to end (lasts about 4ms) __delay_ms(5); // Sends the start signal: low for at least 1ms, then high for 20 to 40us DHT22_PIN_DIR = 0; // configure as output, then set it as 0 (= LATAbits.LATA4). __delay_ms(2); DHT22_PIN_DIR = 1; // configure as input, then set it as 1 (through pullup). __delay_us(40); // Check DHT start response waitDHTOrRet(0); // DHT pulls low waitDHTOrRet(1); // DHT pulls high for 80ms __delay_us(40); waitDHTOrRet(0); // DHT pulls low // Read the 5 DHT payload bytes in dhtBytes for (uint8_t n = 0; n < 5; n++) { for (int8_t i = 7; i >= 0; i--) { waitDHTOrRet(1); // Wait for up CTRL_1 = 1; waitDHTOrRet(0); // Wait for low. Waited time is TMR0. CTRL_1 = 0; if (TMR0 > 50) { // Low: 26-28us High: 70us dhtBytes[n] |= 1 << i; } } } return 0; } // Fetches humidity & temp from DHT, returns 0 if error int fetchClimate(int8_t* humidity, int8_t* temperature) { if(readDHT()) return 1; uint8_t checksum = dhtBytes[0] + dhtBytes[1] + dhtBytes[2] + dhtBytes[3]; if (dhtBytes[4] != checksum) { return 1; // Checksum error } uint16_t hum = (((uint16_t) (dhtBytes[0])) << 8) | ((uint16_t) dhtBytes[1]); *humidity = (int8_t) (hum / 10); uint16_t temp = (((uint16_t) (dhtBytes[2])) << 8) | ((uint16_t) dhtBytes[3]); int8_t tempRound = (temp % 10) >= 5 ? 1 : 0; if (temp & 0x8000) { // If high bit is 1, temperature is negative. *temperature = - (int8_t) ((temp & 0x7FFF) / 10) - tempRound; }else { *temperature = (int8_t) (temp / 10) + tempRound; } return 0; } void main() { // 8MHz internal clock OSCCON = 0b01110000; // Ping config TRISA = 0b11011011; // Declare RA2 and RA5 as output (bit = 0) ANSELA = 0b00000011; // Declare used pins as digital I/O (bit = 0) WPUA = 0b00010000; // Active la résistance de pull-up sur RA4 LATAbits.LATA4 = 0; // Declare RA4 output value as 0 (only effective when DHT22_PIN_DIR = 0) // Timer 0 config OPTION_REGbits.PSA = 0; // Enable prescaler OPTION_REGbits.PS = 0b000; // 1/2 prescaler OPTION_REGbits.TMR0CS = 0; // Use internal clock OPTION_REGbits.TMR0SE = 0; // Increment on rising edge while (1) { int8_t hum = 0; int8_t temp = 0; int is_error = fetchClimate(&hum, &temp); if(is_error){ __delay_ms(5000); } __delay_ms(200); } }