1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
4 * 2019/8/28 - ROBIN KRENS
8 * DS18B20 temperature sensor implementation
9 * Uses the 1-wire protocol. You will need to setup the temperature sensor
10 * with an external pull up resistor. High is the idle state of the chip.
11 * This implementation does not use parasite power. Uses busy waits.
12 * The chip doesn't require too accurate timings. Busy waits are between 15
13 * and 240 microseconds.
15 * The temperature conversion on the chip it takes a lot longer (up to 700ms).
16 * In case temperature is often read, implementing this with interrupts might be
19 * Each series of commands is initiated with a long reset and prescence pulse.
22 * - Convert and read temperature
25 * - Scratchpad copy functionality (+EEPROM)
26 * - Alarm functionality
35 #include <sys/robsys.h>
37 #include <lib/regfunc.h>
38 #include <lib/string.h>
39 #include <lib/tinyprintf.h>
41 #include <drivers/tsensor.h>
46 #define READ_SCRATCH 0xBE
47 #define CONVERT_T 0x44
49 /* Basic GPIO settings for output pulses and input */
50 static void in_conf() {
51 rwrite(GPIOB_CRL, 0x44444444);
54 static void out_conf() {
55 rwrite(GPIOB_CRL, 0x46444444); // open drain (with external pullup resistor)
58 /* Send command cmd over data wire. Each write slot should be
60 static void send_cmd(unsigned char cmd) {
64 for (int i = 0; i < 8; i++) {
65 // initiate write slot
67 rclrbit(GPIOB_ODR, 6); // pull low
69 // writing a logical 1 or 0
70 if ((cmd >> pos) & 0x01) {
83 /* Read reply of sensor. Depending on the command, the sensor
84 * can send back up to 9 bytes */
85 static char get_byte() {
89 for (int i = 0; i < 8; i++) {
90 /* Initate write slot*/
92 rclrbit(GPIOB_ODR, 6);
94 /* Listen for reply */
96 if (rchkbit(GPIOB_IDR,6)) {
102 /* Each read slot should be at least 60 microseconds
103 * before the next one is initiated */
110 /* Initiate the sensor, send a reset pulse and wait consequently for
111 * presence pulse. Slots should be at least 450 and 240 microseconds.
113 static int tsensor_init() {
115 rsetbit(RCC_APB2ENR, 3); // GPIOB enable
117 /* send presence pulse */
119 rclrbit(GPIOB_ODR, 6); // pull low
121 /* wait for the chips reply */
124 if (!rchkbit(GPIOB_IDR, 6)) {
125 //printf("Info: sensor detected\n");
129 printf("Error: no temperature sensor found!");
132 _block(240); // finish intialization slot
141 /* Wait for the chip to convert the temperature */
142 static void wait_tconvert() {
144 printf("Info: Converting temp\n");
145 /* initiate write slot */
147 rclrbit(GPIOB_ODR, 6);
150 while (!rchkbit(GPIOB_IDR, 6)) {
154 rclrbit(GPIOB_ODR, 6);
160 /* Print some serial and CRC information about the chip */
161 void tsensor_printid() {
166 // replies with 8 bytes
169 char scratchbuf[nbytes];
170 memset(&scratchbuf, 0, sizeof(char) * nbytes);
171 scratchbuf[nbytes+1] = '\n';
173 for (int i = 0; i < nbytes; i++) {
174 scratchbuf[i] = get_byte();
178 printf("Family Code: %#x\n", scratchbuf[0]);
179 printf("Serial Number: 0x");
180 for (int i = 1; i < 7; i++) {
181 printf("%x", scratchbuf[i]);
184 printf("CRC Code: %#x\n", scratchbuf[7]);
188 /* Convert and read temperature of chip. Sensor has to be initialized twice
189 * since there are two series of commands (see datasheet flowchart) */
190 uint16_t tsensor_get_temp() {
192 /* initialize sensor and send commands */
200 send_cmd(READ_SCRATCH);
202 /* Scratchpad is 9 bytes, but we are only interested in
203 * the first two bytes, since they contain the LSB and
204 * MSB of temperature */
207 char scratchbuf[nbytes];
208 memset(&scratchbuf, 0, sizeof(char) * nbytes);
209 scratchbuf[nbytes+1] = '\n';
211 for (int i = 0; i < nbytes; i++) {
212 scratchbuf[i] = get_byte();
215 // LSB first four bits are after floating point
216 // uint8_t lsb_afltp = scratchbuf[0] & 0xF;
218 int8_t lsb_bfltp = (scratchbuf[0] >> 4) & 0xF;
219 // MSB only the first three bits are used
220 uint8_t msb = scratchbuf[1] & 0x7;
222 return (msb << 4) + lsb_bfltp;
230 uint16_t temp = get_temp();
231 printf("Current temperature: %d\n", temp);