// // // serial_button.c // // 115200 baud FTDI connection that outputs '0' or '1' depending // on the state of a physical button // // set lfuse to 0x5E for 20 MHz xtal // // Neil Gershenfeld // 12/8/10 // Erik Strand // 11/26/2018 // #include <avr/io.h> #include <util/delay.h> #include <avr/pgmspace.h> #include "OneWire.h" #define output(directions,pin) (directions |= pin) // set port direction for output #define set(port,pin) (port |= pin) // set port pin #define clear(port,pin) (port &= (~pin)) // clear port pin #define pin_test(pins,pin) (pins & pin) // test for port pin #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set #define bit_delay_time 8.5 // bit delay for 115200 with overhead #define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay #define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay #define char_delay() _delay_ms(10) // char delay #define delay(duration) _delay_ms(duration); // drop-in replacement for Arduino delay #define serial_port PORTA #define serial_direction DDRA #define serial_pins PINA #define serial_pin_in (1 << PA0) #define serial_pin_out (1 << PA1) #define led_pin (1 << PB2) #define button_pin (1 << PA7) #define max_buffer 25 void put_char(volatile unsigned char *port, unsigned char pin, char txchar) { // // send character in txchar on port pin // assumes line driver (inverts bits) // // start bit // clear(*port,pin); bit_delay(); // // unrolled loop to write data bits // if bit_test(txchar,0) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,1) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,2) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,3) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,4) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,5) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,6) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,7) set(*port,pin); else clear(*port,pin); bit_delay(); // // stop bit // set(*port,pin); bit_delay(); // // char delay // bit_delay(); } void put_string(volatile unsigned char *port, unsigned char pin, char *str) { // // print a null-terminated string // static int index; index = 0; do { put_char(port, pin, str[index]); ++index; } while (str[index] != 0); } OneWire ds(11); // on pin 10 (a 4.7K resistor is necessary) //void setup(void) { // Serial.begin(9600); //} void loop(void) { byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; float celsius, fahrenheit; if ( !ds.search(addr)) { put_string(&serial_port, serial_pin_out, "No more addresses."); ds.reset_search(); delay(250); return; } //Serial.print("ROM ="); put_string(&serial_port, serial_pin_out, "ROM="); for( i = 0; i < 8; i++) { put_char(&serial_port, serial_pin_out, ' '); //Serial.print(addr[i], HEX); put_string(&serial_port, serial_pin_out, "xxx"); //put_string(&serial_port, serial_pin_out, addr[i]) } if (OneWire::crc8(addr, 7) != addr[7]) { put_string(&serial_port, serial_pin_out, "CRC is not valid!"); return; } //Serial.println(); // the first ROM byte indicates which chip switch (addr[0]) { case 0x10: put_string(&serial_port, serial_pin_out, " Chip = DS18S20"); // or old DS1820 type_s = 1; break; case 0x28: put_string(&serial_port, serial_pin_out, " Chip = DS18B20"); type_s = 0; break; case 0x22: put_string(&serial_port, serial_pin_out, " Chip = DS1822"); type_s = 0; break; default: put_string(&serial_port, serial_pin_out, "Device is not a DS18x20 family device."); return; } ds.reset(); ds.select(addr); ds.write(0x44, 1); // start conversion, with parasite power on at the end delay(1000); // maybe 750ms is enough, maybe not // we might do a ds.depower() here, but the reset will take care of it. present = ds.reset(); ds.select(addr); ds.write(0xBE); // Read Scratchpad put_string(&serial_port, serial_pin_out, " Data = "); put_string(&serial_port, serial_pin_out, "xxx"); //put_string(&serial_port, serial_pin_out, present, HEX); put_string(&serial_port, serial_pin_out, " "); for ( i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); //Serial.print(data[i], HEX); put_string(&serial_port, serial_pin_out, " thing"); } put_string(&serial_port, serial_pin_out, " CRC="); //put_string(&serial_port, serial_pin_out, OneWire::crc8(data, 8), HEX); // Convert the data to actual temperature // because the result is a 16 bit signed integer, it should // be stored to an "int16_t" type, which is always 16 bits // even when compiled on a 32 bit processor. int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // 9 bit resolution default if (data[7] == 0x10) { // "count remain" gives full 12 bit resolution raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); // at lower res, the low bits are undefined, so let's zero them if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms //// default is 12 bit resolution, 750 ms conversion time } celsius = (float)raw / 16.0; fahrenheit = celsius * 1.8 + 32.0; put_string(&serial_port, serial_pin_out, " Temperature = "); //put_string(&serial_port, serial_pin_out, celsius); put_string(&serial_port, serial_pin_out, " Celsius, "); //put_string(&serial_port, serial_pin_out, fahrenheit); put_string(&serial_port, serial_pin_out, " Fahrenheit"); } int main(void) { // Set clock divider to 1. CLKPR = (1 << CLKPCE); CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); // Initialize output pins. set(serial_port, serial_pin_out); output(serial_direction, serial_pin_out); // Configure led pin as an output. DDRB |= led_pin; // Configure button_pin as an input. DDRA &= ~button_pin; // Activate button_pin's pullup resistor. PORTA |= button_pin; while (1) { // Turn on the LED when the button is pressed. if (PINA & button_pin) { // Turn off the LED. PORTB &= ~led_pin; //put_char(&serial_port, serial_pin_out, '0'); } else { PORTB |= led_pin; //put_char(&serial_port, serial_pin_out, '1'); } //_delay_us(10000); loop(); } }