瀏覽代碼

Опрос DS18B20 и вывод температуры.

Vladimir N. Shilov 7 年之前
父節點
當前提交
ae38f89617
共有 3 個文件被更改,包括 271 次插入27 次删除
  1. 7 0
      ReadMe.txt
  2. 201 6
      main.c
  3. 63 21
      main.h

+ 7 - 0
ReadMe.txt

@@ -7,3 +7,10 @@ Indikators:	4 x 4" 7-segment LED indocators "KEM-40011 BSR" with common anode
 LED drivers:	ULN2803 for segments, KT817 for anodes
 LEDs:		2 pcs red led to ground
 Buttons:	7 pcs connected as voltage divider to ADC0
+
+---
+2017.05.30
+
+Сделал опрос DS18B20. Задержки на таймере.
+В идеале хочу реализовать в виде КА в прерывании от таймера,
+с внешним запуском и управлением.

+ 201 - 6
main.c

@@ -21,7 +21,7 @@ __C_task void main(void)
   INDCTR_COMMON_PORT = ~INDCTR_COMMON_ALL; // off all indikators
 
   for(i=0; i<INDCTR_NUMS; i++) {
-    Display[i] = IndctrNums[i];
+    Display[i] = Sym_minus;
   }
 
   Flag.needDot = 0;
@@ -31,10 +31,8 @@ __C_task void main(void)
   TCNT0 = TIM0_CNT; // load timer
   TIMSK |= 1<<TOIE0; // enable TIM0_OVF interrupt
 
-  /* Timer0 every 4 ms switch showing LED */
-  TCCR0 = TIM0_PRESCALER;
-  TCNT0 = TIM0_CNT; // load timer
-  TIMSK |= 1<<TOIE0; // enable TIM0_OVF interrupt
+  /* Timer1 ticks with 1 MHz frequency for DS18B20 delays */
+  TCCR1B = TIM1_PRESCALER;
 
   /* ADC init */
   resultADC = 0;
@@ -51,11 +49,13 @@ __C_task void main(void)
 
   // Tasks for sheduler
   RTOS_SetTask(startADC,0,50);
-  RTOS_SetTask(getTime,0,500);
+  RTOS_SetTask(getTime,4,500);
+  RTOS_SetTask(ds18b20_StartMeasure,8,10000);
   
   /* Get time */
 
   while(1) {
+    /*
     if (1 == Flag.newTime) {
       Flag.newTime = 0;
 
@@ -64,6 +64,20 @@ __C_task void main(void)
       Display[2] = IndctrNums[(0x0F & (Clock.minutes>>4))];
       Display[3] = IndctrNums[(0x0F & Clock.minutes)];
     }
+    */
+
+    if (1 == Flag.newTemp) {
+      Flag.newTemp = 0;
+
+      if (Temperature < 0) {
+        Display[0] = Sym_minus;
+      } else {
+        Display[0] = Sym_blank;
+      }
+      Display[1] = IndctrNums[(0x0F & (Temperature>>4))];
+      Display[2] = IndctrNums[(0x0F & Temperature)];
+      Display[3] = Sym_gradus;
+    }
 
     if (1 == Flag.newBTN) {
       Flag.newBTN = 0;
@@ -160,6 +174,177 @@ static void setTime(void) {
   TWI_SendData(twi_buf, 5);
 }
 
+static uint8_t ds18b20_Reset(void) {
+  uint8_t i;
+
+  /* Pull line low and wait for 480uS */
+  DS18B20_LOW;
+  DS18B20_OUTPUT_MODE;
+
+  //ds18b20_delay(us(480));
+  Flag.T1OC = 0;
+  TCNT1 = 0;
+  OCR1A = 480;
+  TIMSK |= (1<<OCF1A);
+  while (0 == Flag.T1OC) {
+    MCUCR = 1<<SE;
+    __sleep();
+  }
+  Flag.T1OC = 0;
+
+  /* Release line and wait for 60uS */
+  DS18B20_INPUT_MODE;
+  //ds18b20_delay(us(60));
+  TCNT1 = 0;
+  OCR1A = 60;
+  OCR1B = 420;
+  TIMSK |= (1<<OCF1B);
+  while (0 == Flag.T1OC) {
+    MCUCR = 1<<SE;
+    __sleep();
+  }
+  Flag.T1OC = 0;
+
+  /* Store line value and wait until the completion of 480uS period */
+  i = DS18B20_VALUE;
+  //ds18b20_delay(us(420));
+  while (0 == Flag.T1OC) {
+    MCUCR = 1<<SE;
+    __sleep();
+  }
+  TIMSK &= ~((1<<OCF1A) | (1<<OCF1B));
+
+  /* Return the value read from the presence pulse (0=OK, else=WRONG) */
+  return i;
+}
+
+static void ds18b20_WriteBit(uint8_t bit) {
+  /* Pull line low for 1uS */
+  DS18B20_LOW;
+  DS18B20_OUTPUT_MODE;
+  //ds18b20_delay(us(1));
+  __delay_cycles(8);
+
+  /* If we want to write 1, release the line (if not will keep low) */
+  if(1 == bit) {
+    DS18B20_INPUT_MODE;
+  }
+
+  /* Wait for 60uS and release the line */
+  //ds18b20_delay(us(60));
+  Flag.T1OC = 0;
+  TCNT1 = 0;
+  OCR1A = 60;
+  TIMSK |= (1<<OCF1A);
+  while (0 == Flag.T1OC) {
+    MCUCR = 1<<SE;
+    __sleep();
+  }
+  TIMSK &= ~(1<<OCF1A);
+
+  DS18B20_INPUT_MODE;
+}
+
+static uint8_t ds18b20_ReadBit(void) {
+  uint8_t bit=0;
+
+  /* Pull line low for 1uS */
+  DS18B20_LOW;
+  DS18B20_OUTPUT_MODE;
+  //ds18b20_delay(us(1));
+  __delay_cycles(8);
+
+  /* Release line and wait for 14uS */
+  DS18B20_INPUT_MODE;
+  //ds18b20_delay(us(14));
+  Flag.T1OC = 0;
+  TCNT1 = 0;
+  OCR1A = 14;
+  OCR1B = 45;
+  TIMSK |= (1<<OCF1A) | (1<<OCF1B);
+  while (0 == Flag.T1OC) {
+    MCUCR = 1<<SE;
+    __sleep();
+  }
+  Flag.T1OC = 0;
+
+  /* Read line value */
+  if (DS18B20_VALUE != 0) {
+    bit = 0x80;
+  }
+
+  /* Wait for 45uS to end and return read value */
+  //ds18b20_delay(us(45));
+  while (0 == Flag.T1OC) {
+    MCUCR = 1<<SE;
+    __sleep();
+  }
+  TIMSK &= ~((1<<OCF1A) | (1<<OCF1B));
+
+  return bit;
+}
+
+static uint8_t ds18b20_ReadByte(void) {
+  uint8_t i=8, n=0;
+
+  while (i--) {
+    /* Shift one position right and store read value */
+    n >>= 1;
+    n |= ds18b20_ReadBit();
+  }
+  return n;
+}
+
+static void ds18b20_WriteByte(uint8_t byte) {
+  uint8_t i=8;
+
+  while (i--) {
+    /* Write actual bit and shift one position right to make the next bit ready */
+    ds18b20_WriteBit(byte & 0x01);
+    byte >>= 1;
+  }
+}
+
+static void ds18b20_StartMeasure(void) {
+  /* Reset, skip ROM and start temperature conversion */
+  if (ds18b20_Reset() != 0) {
+    Temperature = -99;
+    Flag.newTemp = 1;
+  } else {
+    ds18b20_WriteByte(DS18B20_CMD_SKIPROM);
+    ds18b20_WriteByte(DS18B20_CMD_CONVERTTEMP);
+    RTOS_SetTask(ds18b20_ReadTemperature, 750, 0);
+  }
+}
+
+static void ds18b20_ReadTemperature(void) {
+  uint8_t temperature[2];
+  int8_t digit;
+
+  /* Reset, skip ROM and send command to read Scratchpad */
+  if (ds18b20_Reset() != 0) {
+    Temperature = -98;
+  } else {
+    ds18b20_WriteByte(DS18B20_CMD_SKIPROM);
+    ds18b20_WriteByte(DS18B20_CMD_RSCRATCHPAD);
+
+    /* Read Scratchpad (only 2 first bytes) */
+    temperature[0]=ds18b20_ReadByte();
+    temperature[1]=ds18b20_ReadByte();
+
+    //ds18b20_reset();
+
+    /* Store temperature integer digits */
+    digit=temperature[0]>>4;
+    digit|=(temperature[1]&0x7)<<4;
+
+    /* Get only integer part of temperature */
+    Temperature = digit / 16;
+  }
+
+  Flag.newTemp = 1;
+}
+
 
 /**
  *  I n t e r r u p t   h a n d l e r s
@@ -206,6 +391,16 @@ __interrupt void TIMER0_OVF_ISR(void) {
   }
 }
 
+#pragma vector=TIMER1_COMPA_vect
+__interrupt void TIMER1_COMPA_ISR(void) {
+  Flag.T1OC = 1;
+}
+
+#pragma vector=TIMER1_COMPB_vect
+__interrupt void TIMER1_COMPB_ISR(void) {
+  Flag.T1OC = 1;
+}
+
 #pragma vector=ADC_vect
 __interrupt void ADC_ISR(void) {
   resultADC = ADCH;

+ 63 - 21
main.h

@@ -26,6 +26,13 @@
 /* 7-segment LED indikators */
 #define INDCTR_NUMS                4
 
+/**
+ *   A
+ * F   B
+ *   G
+ * E   C
+ *   D   H
+ */
 #define INDCTR_SEGMENT_PORT        PORTB
 #define INDCTR_SEGMENT_DDR         DDRB
 #define INDCTR_SEGMENT_A           PB0
@@ -48,26 +55,29 @@
 #define INDCTR_COMMON_DOT          1
 
 typedef enum {
-  Sym_0 = ~0x28,
-  Sym_1 = ~0xEB,
-  Sym_2 = ~0x32,
-  Sym_3 = ~0xA2,
-  Sym_4 = ~0xE1,
-  Sym_5 = ~0xA4,
-  Sym_6 = ~0x24,
-  Sym_7 = ~0xEA,
-  Sym_8 = ~0x20,
-  Sym_9 = ~0xA0,
-  Sym_a = ~0x60,
-  Sym_b = ~0x25,
-  Sym_c = ~0x37,
-  Sym_d = ~0x23,
-  Sym_e = ~0x34,
-  Sym_f = ~0x74,
-  Sym_minus = ~0xF7,
-  Sym_gradus = ~0xF0,
-  Sym_t = ~0x35,
-  Sym_dot = 1<<INDCTR_SEGMENT_H
+  Sym_0 = 0xD7,
+  Sym_1 = 0x14,
+  Sym_2 = 0xCD,
+  Sym_3 = 0x5D,
+  Sym_4 = 0x1E,
+  Sym_5 = 0x5B,
+  Sym_6 = 0xDB,
+  Sym_7 = 0x19,
+  Sym_8 = 0xDF,
+  Sym_9 = 0x5F,
+  Sym_a = 0x9F,
+  Sym_b = 0xDA,
+  Sym_c = 0xC8,
+  Sym_d = 0xDC,
+  Sym_e = 0xCB,
+  Sym_f = 0x8B,
+  Sym_minus = 1<<INDCTR_SEGMENT_G,
+  Sym_minus_t = 1<<INDCTR_SEGMENT_A,
+  Sym_minus_b = 1<<INDCTR_SEGMENT_D,
+  Sym_gradus = 0x0F,
+  Sym_t = 0xCA,
+  Sym_dot = 1<<INDCTR_SEGMENT_H,
+  Sym_blank = 0x00
 } indctr_sym_t;
 
 /* Convert 0x0-0xF digit to 7-seg indicators symbol */
@@ -80,11 +90,41 @@ const indctr_sym_t IndctrNums[16] = {
 
 
 /* DS18B20 termometer */
+#define DS18B20_CMD_CONVERTTEMP   0x44
+#define DS18B20_CMD_RSCRATCHPAD   0xbe
+#define DS18B20_CMD_WSCRATCHPAD   0x4e
+#define DS18B20_CMD_CPYSCRATCHPAD 0x48
+#define DS18B20_CMD_RECEEPROM     0xb8
+#define DS18B20_CMD_RPWRSUPPLY    0xb4
+#define DS18B20_CMD_SEARCHROM     0xf0
+#define DS18B20_CMD_READROM       0x33
+#define DS18B20_CMD_MATCHROM      0x55
+#define DS18B20_CMD_SKIPROM       0xcc
+#define DS18B20_CMD_ALARMSEARCH   0xec
+
 #define DS18B20_PORT            PORTD
 #define DS18B20_DDR             DDRD
 #define DS18B20_PIN             PIND
 #define DS18B20_PAD             PD7
 
+#define DS18B20_INPUT_MODE      DS18B20_DDR&=~(1<<DS18B20_PAD)
+#define DS18B20_OUTPUT_MODE     DS18B20_DDR|=(1<<DS18B20_PAD)
+#define DS18B20_LOW             DS18B20_PORT&=~(1<<DS18B20_PAD)
+#define DS18B20_HIGH            DS18B20_PORT|=(1<<DS18B20_PAD)
+#define DS18B20_VALUE           (DS18B20_PIN & (1<<DS18B20_PAD))
+
+static int8_t Temperature;
+
+static uint8_t ds18b20_Reset(void);
+static void ds18b20_WriteBit(uint8_t bit);
+static uint8_t ds18b20_ReadBit(void);
+static uint8_t ds18b20_ReadByte(void);
+static void ds18b20_WriteByte(uint8_t byte);
+static void ds18b20_StartMeasure(void);
+static void ds18b20_ReadTemperature(void);
+
+#define TIM1_PRESCALER          (1<<CS11)
+
 /* BTN */
 #define BTN_LVL_NO              0xED
 #define BTN_LVL_7               0xD8
@@ -119,8 +159,10 @@ typedef struct {
 volatile struct {
   uint8_t needDot       : 1;
   uint8_t newTime       : 1;
+  uint8_t newTemp       : 1;
   uint8_t newBTN        : 1;
-  uint8_t               : 5; // дополнение до 8 бит (резерв) 
+  uint8_t T1OC          : 1;
+  uint8_t               : 3; // дополнение до 8 бит (резерв) 
 } Flag;
 
 volatile static indctr_sym_t Display[4];