|
- /********************************
- DS18B20測溫程序
- 文件名:main.c
- 編譯:WinAVR-20070122
- 硬件環(huán)境:CA-M8X 打開的開關(guān)如下
- S6(1,2,5,6,7) - 外部4MHz晶振和595接口
- J8(EN-SEG) - 數(shù)碼管顯示允許
- S7(4) - 連接PC1 與DS18B20數(shù)據(jù)口
- (在CA-M8X 上DS18B20為非總線供電)
-
- 芯藝設(shè)計(jì)室 2004-2007 版權(quán)所有
- 轉(zhuǎn)載請保留本注釋在內(nèi)的全部內(nèi)容
- Email: changfutong@sina.com
- *******************************/
- #include <avr/io.h>
- #include <util/delay.h>
- #include <stdint.h>
- #include "seg.h" //聲明數(shù)碼管顯示接口函數(shù)
- #define CLR_1WIRE_BUS DDRC|=_BV(PC1) //設(shè)置為輸出,此時(shí)由于PORTC1是低所以輸出低
- #define SET_1WIRE_BUS DDRC&=~_BV(PC1)//設(shè)置為輸入,此時(shí)由于PORTC1是低所以程高阻,又因?yàn)橥獠坑猩侠娮杷韵喈?dāng)于設(shè)置總線為高
- #define GET_1WIRE_BUS PINC&_BV(PC1)
- #define DS18B20_READ_ROM 0x33
- #define DS18B20_MATCH_ROM 0X55
- #define DS18B20_SKIP_ROM 0XCC
- #define DS18B20_SEARCH_ROM 0XF0
- #define DS18B20_ALARM_SEARCH_ROM 0XEC
- #define DS18B20_WRITE_RAM 0X40
- #define DS18B20_READ_RAM 0XBE
- #define DS18B20_COPY_RAM 0X48
- #define DS18B20_CONVERT_TEM 0X44
- #define DS18B20_EECALL_EEPROM 0XB8
- #define DS18B20_READ_POWER_SUPPLY 0XB4
- //總線端口初始化
- void BusInit(void)
- {
- PORTC&=~_BV(PC1);//此口總保持低
- DDRC&=~_BV(PC1); //初始化為輸入,用外部上拉電阻保持總線的高電平
- }
- //由于系統(tǒng)時(shí)鐘為4MHz,一個(gè)_delay_loop_2正好延時(shí)一us
- #define DelayUs(x) _delay_loop_2(x)
- void DelayMs(uint16_t t)
- {
- uint16_t i;
- for(i=0;i<t;i++)
- _delay_loop_2(250 * 4);
- }
- //單總線復(fù)位
- uint8_t ds18b20_reset(void)
- {
- uint8_t ret=0;
- CLR_1WIRE_BUS;
- DelayUs(500); //拉低總線至少480us
- SET_1WIRE_BUS;
- DelayUs(100);//釋放總線后等待15-60us
- if((GET_1WIRE_BUS)==0)//檢測到DS18B20把總線拉低
- ret=1; //復(fù)位成功
- DelayUs(1000);//等待器件釋放總線
- return ret;
- }
- //單總線讀一字節(jié)
- uint8_t ds18b20_read(void)
- {
- uint8_t data=0;
- uint8_t i=0;
- for(i=0;i<8;i++)
- {
- data>>=1;
- CLR_1WIRE_BUS;
- DelayUs(2);//此時(shí)>1us
- SET_1WIRE_BUS;
- DelayUs(4);//此時(shí)<15us
- if(GET_1WIRE_BUS)
- data|=0x80;
- DelayUs(60);//此時(shí)>60us
- }
- return(data);
- }
- //單總線寫一字節(jié)
- void ds18b20_write(uint8_t data)
- {
- uint8_t i=0;
- for(i=0;i<8;i++)
- {
- if(data&0x01)
- {
- CLR_1WIRE_BUS;
- DelayUs(8);//8us
- SET_1WIRE_BUS;
- DelayUs(55);//55us
- }
- else
- {
- CLR_1WIRE_BUS;
- DelayUs(55);//55us
- SET_1WIRE_BUS;
- DelayUs(20);//8us
- }
- data>>=1;
- }
- }
- //執(zhí)行轉(zhuǎn)換
- uint8_t Ds18b20Convert(uint8_t *t)
- {
- //發(fā)送轉(zhuǎn)換命令
- if(ds18b20_reset()==0)
- return 0;
- ds18b20_write(DS18B20_SKIP_ROM); //忽略地址匹配,總線上只有一個(gè)器件時(shí),或?qū)偩所有器件操作
- ds18b20_write(DS18B20_CONVERT_TEM);//開始轉(zhuǎn)換命令
-
- //等待轉(zhuǎn)換完成,ds18b20默認(rèn)轉(zhuǎn)換精度為12位,此時(shí)最大轉(zhuǎn)換時(shí)間為750ms
- DelayMs(1000);
-
- //讀溫度字節(jié)
- if(ds18b20_reset()==0)
- return 0;
- ds18b20_write(DS18B20_SKIP_ROM); //忽略地址匹配
- ds18b20_write(DS18B20_READ_RAM); //讀RAM命令
- t[0]=ds18b20_read();
- t[1]=ds18b20_read();
-
- return 1;
- }
- //根據(jù)DS18B20中讀的溫度字節(jié),計(jì)算實(shí)際溫度值
- int8_t GetTemperature(uint8_t *t)
- {
- int8_t ret;
- uint32_t val;
- uint16_t tmp=(t[1]*256)+t[0];
- uint8_t sflag=0;
- if((t[1]&0xf8)==0xf8) //若負(fù)溫度,從補(bǔ)碼轉(zhuǎn)換(取反加一)
- {
- sflag=1;
- tmp=~tmp;
- tmp++;
- }
- tmp&=0x07ff; //確保前5位為0
-
- //乘0.0625操作,為此本函數(shù)只適用于DS18B20 12位轉(zhuǎn)換(默認(rèn))時(shí)
- val=((uint32_t)tmp)*625;
- val/=10000;
-
- ret=(int8_t)val;
-
- if(sflag)
- ret|=0x80;//變負(fù)數(shù)
-
- return ret;
- }
- //測試主函數(shù)
- int main(void)
- {
- uint8_t tmp[2];//保存溫度字節(jié)
- int8_t tval; //保存溫度值
-
- SegInit();//數(shù)碼管初始化
- SegNumberOut(0,0);//顯示 0
- BusInit(); //單總線I/O口初始化
- while(1)
- {
- if(Ds18b20Convert(tmp))//如果轉(zhuǎn)換成功
- {
- tval=GetTemperature(tmp);//計(jì)算實(shí)際溫度值
- if(tval>=0)
- SegNumberOut(tval,0);//十進(jìn)制顯示溫度值
- else
- SegNumberOut(0,0);//數(shù)碼管無法顯示負(fù)數(shù),只能顯示0
- }
- }
- return 0;
- }
- seg.c文件:
- /********************************
- 74HC95驅(qū)動的數(shù)碼管顯示模塊
- 文件名:seg.c
- 編譯:WinAVR-20070122
- 硬件環(huán)境:CA-M8X 打開的開關(guān)如下
- S6(1,2,5,6,7) - 外部4MHz晶振和595接口
- J8(EN-SEG) - 數(shù)碼管顯示允許
-
- 芯藝設(shè)計(jì)室 2004-2007 版權(quán)所有
- 轉(zhuǎn)載請保留本注釋在內(nèi)的全部內(nèi)容
- WEB: http://www.chipart.cn
- Email: changfutong@sina.com
- *******************************/
- #include <avr/io.h>
- #include <util/delay.h>
- #include <stdint.h>
- #include "seg.h"
- #define SER_PORT PORTD
- #define SER_DAT PD4
- #define SER_RCK PD5
- #define SER_SCK PD6
- //顯示碼(可從chipart.cn下載生成工具)
- static uint8_t g_aDisplayBuf[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
- //向595 寫一字節(jié)
- static void ser_out(uint8_t dat)
- {
- uint8_t i;
- for(i=0;i<8;i++)
- {
- if(dat&0x80)
- SER_PORT|=_BV(SER_DAT);
- else
- SER_PORT&=~_BV(SER_DAT);
-
- //產(chǎn)生移位脈沖
- SER_PORT|=_BV(SER_SCK);
- SER_PORT&=~_BV(SER_SCK);
- dat<<=1;
- }
- }
- //數(shù)碼管顯示數(shù)(0~255)
- //num :顯示的數(shù) hex:是否用十六進(jìn)制顯示
- void SegNumberOut(uint8_t num,uint8_t hex)
- {
- uint8_t buf[2];//發(fā)送顯示碼緩沖區(qū)
- uint8_t temp;
-
- if(hex) //十六進(jìn)制
- {
- buf[0]=g_aDisplayBuf[num>>4];//高位
- buf[1]=g_aDisplayBuf[num&0x0f];//低位
- }
- else//十進(jìn)制
- {
- buf[1]=g_aDisplayBuf[num%10];
- temp=num%100;
- buf[0]=g_aDisplayBuf[temp/10];
- temp=num/100;
-
- if(temp>0)
- buf[1]|=0x80; //第一個(gè)數(shù)碼管小數(shù)點(diǎn)表示百位1
- if(temp>1)
- buf[0]|=0x80;//兩個(gè)數(shù)碼管小數(shù)點(diǎn)表示百位2
- }
-
- //串行發(fā)送數(shù)據(jù)
- ser_out(buf[0]);
- ser_out(buf[1]);
- //產(chǎn)生鎖存脈沖
- SER_PORT|=_BV(SER_RCK);
- SER_PORT&=~_BV(SER_RCK);
- }
- void SegInit(void)
- {
- //595控制I/O初始化
- DDRD=_BV(SER_DAT)|_BV(SER_SCK)|_BV(SER_RCK);
- SER_PORT&=~_BV(SER_SCK);
- SER_PORT&=~_BV(SER_RCK);
- }
復(fù)制代碼
|
|