代码:
ds18b20.c
/*《AVR专题精选》随书例程3.通信接口使用技巧项目:1-Wire 单总线的使用文件:ds1820.c说明:DS18B20驱动文件。为了简单,没有读取芯片地址,也没有计算校验作者:邵子扬时间:2012年12月13日*/
#include "owi.h"
#include "DS1820.h"/*! \brief Read the temperature from a DS1820 temperature sensor.** This function will start a conversion and read back the temperature* from a DS1820 temperature sensor.** \param bus A bitmask of the bus where the DS1820 is located.* * \param id The 64 bit identifier of the DS1820.** \return The 16 bit signed temperature read from the DS1820.*//*
signed int DS1820_ReadTemperature(unsigned char bus, unsigned char * id)
{signed int temperature;// Reset, presence.if (!OWI_DetectPresence(bus)){return DS1820_ERROR; // Error}// Match the id found earlier.OWI_MatchRom(id, bus);// Send start conversion command.OWI_SendByte(DS1820_START_CONVERSION, bus);// Wait until conversion is finished.// Bus line is held low until conversion is finished.while (!OWI_ReadBit(bus)){}// Reset, presence.if(!OWI_DetectPresence(bus)){return DS1820_ERROR; // Error}// Match id again.OWI_MatchRom(id, bus);// Send READ SCRATCHPAD command.OWI_SendByte(DS1820_READ_SCRATCHPAD, bus);// Read only two first bytes (temperature low, temperature high)// and place them in the 16 bit temperature variable.temperature = OWI_ReceiveByte(bus);temperature |= (OWI_ReceiveByte(bus) << 8);return temperature;
}
*/// 读取温度的简单函数,忽略了ROM识别,适合总线上只有1个 DS1820
// 的应用情况。
signed int DS1820_SimpleReadTemperature(unsigned char pin)
{signed int temperature;OWI_DetectPresence(pin);OWI_SkipRom(pin);OWI_SendByte(DS1820_START_CONVERSION, pin);OWI_DetectPresence(pin);OWI_SkipRom(pin);OWI_SendByte(DS1820_READ_SCRATCHPAD, pin);temperature = OWI_ReceiveByte(pin);temperature |= (OWI_ReceiveByte(pin) << 8);return temperature/16;
}
ds2413.c
/*《AVR专题精选》随书例程3.通信接口使用技巧项目:1-Wire 单总线的使用文件:ds2413.c说明:DS2413驱动文件。为了简单,没有读取芯片地址,也没有计算校验作者:邵子扬时间:2012年12月13日*/
#include "owi.h"
#include "DS2413.h"// 读取DS2413状态
// pin: IO引脚序号
// 端口需要在cfg.h中预先指定
unsigned char DS2413_SimpleRead(unsigned char pin)
{unsigned char PIO;// 检测设备OWI_DetectPresence(pin);// 忽略ROM地址OWI_SkipRom(pin);// 发送读取命令OWI_SendByte(DS2413_PIO_Access_Read, pin);OWI_ReceiveByte(pin);OWI_ReceiveByte(pin);// 读取数据PIO = OWI_ReceiveByte(pin);OWI_DetectPresence(pin);return PIO;
}// 写入数据到 DS2413
// dat: 需要些入的数据
// pin: IO端口序号
unsigned char DS2413_SimpleWrite(unsigned char dat, unsigned char pin)
{unsigned char PIO;// 检测芯片if(!OWI_DetectPresence(pin))return DS2413_ERROR;// 忽略地址OWI_SkipRom(pin);// 发送写入命令OWI_SendByte(DS2413_PIO_Access_Write, pin);// 发送数据OWI_SendByte(dat, pin);// 发送数据补码OWI_SendByte(~dat, pin);OWI_ReceiveByte(pin);// 读取数据PIO = OWI_ReceiveByte(pin);if(!OWI_DetectPresence(pin))return DS2413_ERROR;return PIO;
}
lcd.c
/*《AVR专题精选》随书例程3.通信接口使用技巧项目:1-Wire 单总线的使用文件:lcd.c说明:16x1字符型液晶驱动文件作者:邵子扬时间:2012年12月13日*/
#include <avr/io.h>
#include "macromcu.h"#include "cfg.h"#include <util/delay.h>#define LCDDDR MACRO_CONCAT2(DDR, LCD_PORT)
#define LCDDATA_IN MACRO_CONCAT2(PIN, LCD_PORT)
#define LCDDATA_OUT MACRO_CONCAT2(PORT,LCD_PORT)// 向液晶控制器发送命令
void lcd_write(unsigned char RS, unsigned char dat)
{// 等待液晶内部操作完成// 使用延时法,没有读取标志位_delay_us(50);PINOUT(LCD_RS, RS);LCDDATA_OUT = dat;PINSET(LCD_E);PINCLR(LCD_E);
}// 液晶初始化
void lcd_init()
{LCDDDR = 0xFF;PINDIR(LCD_E, PIN_OUTPUT);PINDIR(LCD_RW, PIN_OUTPUT);PINDIR(LCD_RS, PIN_OUTPUT);PINCLR(LCD_E);PINCLR(LCD_RW);_delay_ms(5);lcd_write(0, 0x30);lcd_write(0, 0x01);_delay_ms(2);lcd_write(0, 0x06);lcd_write(0, 0x0C);
}// 在指定位置显示字符
void lcd_chr(unsigned char x, unsigned char dat)
{lcd_write(0, 0x80 + x); // 设置地址lcd_write(1, dat); // 写入字符数据
}// HEX数据转换为字符
unsigned char HexToChr(unsigned char dat)
{if(dat > 15)return '0';if(dat >9)return dat - 10 + 'A';return dat + '0';
}// 显示HEX数据
void lcd_hex(unsigned char x, unsigned char dat)
{lcd_chr(x, HexToChr(dat/16));lcd_chr(x+1, HexToChr(dat%16));
}// 显示字符串
void lcd_str(unsigned char x, char *s)
{while(*s){lcd_chr(x, *s);x++;s++;}
}
main.c
/*《AVR专题精选》随书例程3.通信接口使用技巧项目:1-Wire 单总线的使用文件:main.c说明:主程序文件。演示了温度传感器DS18B20和双通道开关DS2413的基本用法作者:邵子扬时间:2012年12月13日*/
#include <avr/io.h>#include "cfg.h"
#include "macromcu.h"
#include "lcd.h"#include "owi.h"
#include "ds1820.h"
#include "ds2413.h"#include <util/delay.h>unsigned char cnt=0;
volatile unsigned char stat;
volatile signed int temperature;
char s[10];// 初始化
void init()
{lcd_init(); // 液晶显示器初始化
}int main()
{init();// 向DS2413写入数据0xFFDS2413_SimpleWrite(0xFF, OWI_PIN1);while(1){_delay_ms(1000); // 延时1秒cnt++; // 计数器累加lcd_hex(0, cnt); // 显示// 通过DS18B20读取温度temperature = DS1820_SimpleReadTemperature(OWI_PIN2);// 将结果转换为字符串// 判断符号位if(temperature < 0){s[0] = '-';temperature = -temperature;}elses[0] = '+';s[1] = temperature/100 + '0';temperature = temperature % 100;s[2] = temperature/10 + '0';s[3] = temperature%10 + '0';s[4] = 0;// 显示温度lcd_str(5, s);// 读取DS2413状态stat = DS2413_SimpleRead(OWI_PIN1);if(stat & 0x04)stat = 0xFF;elsestat = 0xFE;// 根据按键状态更新LEDstat = DS213_SimpleWrite(stat, OWI_PIN1); // 更新显示lcd_hex(14, stat);}return 0;
}
owi.c
/*《AVR专题精选》随书例程3.通信接口使用技巧项目:1-Wire 单总线的使用文件:owi.c说明:1-Wire驱动文件。从AVR318例程移植而来,并做了一定优化作者:邵子扬时间:2012年12月13日*/
#include "owi.h"// Port configuration registers for 1-Wire buses.//!< 1-Wire PORT Data register.
#define OWIPORT MACRO_CONCAT2(PORT, OWI_PORT)
//!< 1-Wire Input pin register.
#define OWIPIN MACRO_CONCAT2(PIN, OWI_PORT)
//!< 1-Wire Data direction register.
#define OWIDDR MACRO_CONCAT2(DDR, OWI_PORT)/*! \brief Compute the CRC8 value of a data set.** This function will compute the CRC8 or DOW-CRC of inData using seed* as inital value for the CRC.** \param inData One byte of data to compute CRC from.** \param seed The starting value of the CRC.** \return The CRC8 of inData with seed as initial value.** \note Setting seed to 0 computes the crc8 of the inData.** \note Constantly passing the return value of this function * As the seed argument computes the CRC8 value of a* longer string of data.*/
unsigned char OWI_CRC8(unsigned char inData, unsigned char seed)
{unsigned char bitsLeft;unsigned char temp;for (bitsLeft = 8; bitsLeft > 0; bitsLeft--){temp = ((seed ^ inData) & 0x01);if (temp == 0){seed >>= 1;}else{seed ^= 0x18;seed >>= 1;seed |= 0x80;}inData >>= 1;}return seed;
}/*! \brief Calculate and check the CRC of a 64 bit ROM identifier.* * This function computes the CRC8 value of the first 56 bits of a* 64 bit identifier. It then checks the calculated value against the* CRC value stored in ROM.** \param romvalue A pointer to an array holding a 64 bit identifier.** \retval OWI_CRC_OK The CRC's matched.* \retval OWI_CRC_ERROR There was a discrepancy between the calculated and the stored CRC.*/
unsigned char OWI_CheckRomCRC(unsigned char * romValue)
{unsigned char i;unsigned char crc8 = 0;for (i = 0; i < 7; i++){crc8 = OWI_CRC8(*romValue, crc8);romValue++;}if (crc8 == (*romValue)){return OWI_CRC_OK;}return OWI_CRC_ERROR;
}/*! \brief Initialization of the one wire bus(es). (Software only driver)* * This function initializes the 1-Wire bus(es) by releasing it and* waiting until any presence sinals are finished.** \param pins A bitmask of the buses to initialize.*/
void OWI_Init(unsigned char pins)
{OWI_RELEASE_BUS(pins);// The first rising edge can be interpreted by a slave as the end of a// Reset pulse. Delay for the required reset recovery time (H) to be // sure that the real reset is interpreted correctly._delay_us(OWI_DELAY_H_STD_MODE);
}/*! \brief Write a '1' bit to the bus(es). (Software only driver)** Generates the waveform for transmission of a '1' bit on the 1-Wire* bus.** \param pins A bitmask of the buses to write to.*/
void OWI_WriteBit1(unsigned char pins)
{unsigned char intState;// Disable interrupts.intState = __save_interrupt();cli();// Drive bus low and delay.OWI_PULL_BUS_LOW(pins);_delay_us(OWI_DELAY_A_STD_MODE);// Release bus and delay.OWI_RELEASE_BUS(pins);_delay_us(OWI_DELAY_B_STD_MODE);// Restore interrupts.__restore_interrupt(intState);
}/*! \brief Write a '0' to the bus(es). (Software only driver)** Generates the waveform for transmission of a '0' bit on the 1-Wire(R)* bus.** \param pins A bitmask of the buses to write to.*/
void OWI_WriteBit0(unsigned char pins)
{unsigned char intState;// Disable interrupts.intState = __save_interrupt();cli();// Drive bus low and delay.OWI_PULL_BUS_LOW(pins);_delay_us(OWI_DELAY_C_STD_MODE);// Release bus and delay.OWI_RELEASE_BUS(pins);_delay_us(OWI_DELAY_D_STD_MODE);// Restore interrupts.__restore_interrupt(intState);
}/*! \brief Read a bit from the bus(es). (Software only driver)** Generates the waveform for reception of a bit on the 1-Wire(R) bus(es).** \param pins A bitmask of the bus(es) to read from.** \return A bitmask of the buses where a '1' was read.*/
unsigned char OWI_ReadBit(unsigned char pins)
{unsigned char intState;unsigned char bitsRead;// Disable interrupts.intState = __save_interrupt();cli();// Drive bus low and delay.OWI_PULL_BUS_LOW(pins);_delay_us(OWI_DELAY_A_STD_MODE);// Release bus and delay.OWI_RELEASE_BUS(pins);_delay_us(OWI_DELAY_E_STD_MODE);// Sample bus and delay.bitsRead = OWIPIN & (1 << pins);_delay_us(OWI_DELAY_F_STD_MODE);// Restore interrupts.__restore_interrupt(intState);return bitsRead;
}/*! \brief Send a Reset signal and listen for Presence signal. (software* only driver)** Generates the waveform for transmission of a Reset pulse on the * 1-Wire(R) bus and listens for presence signals.** \param pins A bitmask of the buses to send the Reset signal on.** \return A bitmask of the buses where a presence signal was detected.*/
unsigned char OWI_DetectPresence(unsigned char pins)
{unsigned char intState;unsigned char presenceDetected;// Disable interrupts.intState = __save_interrupt();cli();// Drive bus low and delay.OWI_PULL_BUS_LOW(pins);_delay_us(OWI_DELAY_H_STD_MODE);// Release bus and delay.OWI_RELEASE_BUS(pins);_delay_us(OWI_DELAY_I_STD_MODE);// Sample bus to detect presence signal and delay.presenceDetected = ((~OWIPIN) & (1 << pins));_delay_us(OWI_DELAY_J_STD_MODE);// Restore interrupts.__restore_interrupt(intState);return presenceDetected;
}/*! \brief Sends one byte of data on the 1-Wire(R) bus(es).* * This function automates the task of sending a complete byte* of data on the 1-Wire bus(es).** \param data The data to send on the bus(es).* * \param pins A bitmask of the buses to send the data to.*/
void OWI_SendByte(unsigned char data, unsigned char pins)
{unsigned char temp;unsigned char i;// Do once for each bitfor (i = 0; i < 8; i++){// Determine if lsb is '0' or '1' and transmit corresponding// waveform on the bus.temp = data & 0x01;if (temp){OWI_WriteBit1(pins);}else{OWI_WriteBit0(pins);}// Right shift the data to get next bit.data >>= 1;}
}/*! \brief Receives one byte of data from the 1-Wire(R) bus.** This function automates the task of receiving a complete byte * of data from the 1-Wire bus.** \param pin A bitmask of the bus to read from.* * \return The byte read from the bus.*/
unsigned char OWI_ReceiveByte(unsigned char pin)
{unsigned char data;unsigned char i;// Clear the temporary input variable.data = 0x00;// Do once for each bitfor (i = 0; i < 8; i++){// Shift temporary input variable right.data >>= 1;// Set the msb if a '1' value is read from the bus.// Leave as it is ('0') else.if (OWI_ReadBit(pin)){// Set msbdata |= 0x80;}}return data;
}/*! \brief Sends the SKIP ROM command to the 1-Wire bus(es).** \param pins A bitmask of the buses to send the SKIP ROM command to.*/
void OWI_SkipRom(unsigned char pins)
{// Send the SKIP ROM command on the bus.OWI_SendByte(OWI_ROM_SKIP, pins);
}/*! \brief Sends the READ ROM command and reads back the ROM id.** \param romValue A pointer where the id will be placed.** \param pin A bitmask of the bus to read from.*/
void OWI_ReadRom(unsigned char * romValue, unsigned char pin)
{unsigned char bytesLeft = 8;// Send the READ ROM command on the bus.OWI_SendByte(OWI_ROM_READ, pin);// Do 8 times.while (bytesLeft > 0){// Place the received data in memory.*romValue++ = OWI_ReceiveByte(pin);bytesLeft--;}
}/*! \brief Sends the MATCH ROM command and the ROM id to match against.** \param romValue A pointer to the ID to match against.** \param pins A bitmask of the buses to perform the MATCH ROM command on.*/
void OWI_MatchRom(unsigned char * romValue, unsigned char pins)
{unsigned char bytesLeft = 8; // Send the MATCH ROM command.OWI_SendByte(OWI_ROM_MATCH, pins);// Do once for each byte.while (bytesLeft > 0){// Transmit 1 byte of the ID to match.OWI_SendByte(*romValue++, pins);bytesLeft--;}
}/*! \brief Sends the SEARCH ROM command and returns 1 id found on the * 1-Wire(R) bus.** \param bitPattern A pointer to an 8 byte char array where the * discovered identifier will be placed. When * searching for several slaves, a copy of the * last found identifier should be supplied in * the array, or the search will fail.** \param lastDeviation The bit position where the algorithm made a * choice the last time it was run. This argument * should be 0 when a search is initiated. Supplying * the return argument of this function when calling * repeatedly will go through the complete slave * search.** \param pin A bit-mask of the bus to perform a ROM search on.** \return The last bit position where there was a discrepancy between slave addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED if an error was detected (e.g. a device was connected to the bus during the search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be discovered.** \note See main.c for an example of how to utilize this function.*/
/*
unsigned char OWI_SearchRom(unsigned char * bitPattern, unsigned char lastDeviation, unsigned char pin)
{unsigned char currentBit = 1;unsigned char newDeviation = 0;unsigned char bitMask = 0x01;unsigned char bitA;unsigned char bitB;// Send SEARCH ROM command on the bus.OWI_SendByte(OWI_ROM_SEARCH, pin);// Walk through all 64 bits.while (currentBit <= 64){// Read bit from bus twice.bitA = OWI_ReadBit(pin);bitB = OWI_ReadBit(pin);if (bitA && bitB){// Both bits 1 (Error).newDeviation = OWI_ROM_SEARCH_FAILED;return;}else if (bitA ^ bitB){// Bits A and B are different. All devices have the same bit here.// Set the bit in bitPattern to this value.if (bitA){(*bitPattern) |= bitMask;}else{(*bitPattern) &= ~bitMask;}}else // Both bits 0{// If this is where a choice was made the last time,// a '1' bit is selected this time.if (currentBit == lastDeviation){(*bitPattern) |= bitMask;}// For the rest of the id, '0' bits are selected when// discrepancies occur.else if (currentBit > lastDeviation){(*bitPattern) &= ~bitMask;newDeviation = currentBit;}// If current bit in bit pattern = 0, then this is// out new deviation.else if ( !(*bitPattern & bitMask)) {newDeviation = currentBit;}// IF the bit is already 1, do nothing.else{}}// Send the selected bit to the bus.if ((*bitPattern) & bitMask){OWI_WriteBit1(pin);}else{OWI_WriteBit0(pin);}// Increment current bit. currentBit++;// Adjust bitMask and bitPattern pointer. bitMask <<= 1;if (!bitMask){bitMask = 0x01;bitPattern++;}}return newDeviation;
}
*/
仿真