|
/*****************************************************
这是用18B20测温度的程式,用MC14489驱动LED数码管显示,
这里只是程式的一部分,已经测试过,可以正确的显示,串口部分
可以用串口调试软件来测试,程式并没有完善好,尚有一些问题没有修改。
由于本人是刚刚学的AVR,从OURAVR学了不少知识,把这部分拿出来献丑了。
软件:CodeVisionAVR
人物:EvanL
*************************************************/
#include<mega8515.h>
#include<delay.h>
#include<stdio.h>
#include<math.h>
#include <1wire.h>
#include<ds18b20.h> // DS1820 Temperature Sensor functions
/*************************************************************/
// 1 Wire Bus functions
#asm
.equ __w1_port=0x15;PORTC //PC3 1 Wire Device(DS18B20)input
.equ __w1_bit=3 //18B20端口设置,由于18B20是双向输入输出
#endasm
/**********************************************************/
#define uchar unsigned char
#define uint unsigned int
#define DATA PORTC.4 //MC14489的数据端;
#define CLK PORTC.2 //MC14489的时钟端;
#define ENA PORTC.0 //MC14489的使能端;
#define MAX_DEVICES 8
/*****************************************************************/
/*串口代码,发送,波特率9600,这段代码是由CVAVR自己产生的*/
/*****************************************************************/
#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7
#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)
// USART Transmitter buffer
#define TX_BUFFER_SIZE 8
char tx_buffer[TX_BUFFER_SIZE];
#if TX_BUFFER_SIZE<256
unsigned char tx_wr_index,tx_rd_index,tx_counter;
#else
unsigned int tx_wr_index,tx_rd_index,tx_counter;
#endif
// USART Transmitter interrupt service routine
interrupt [USART_TXC] void usart_tx_isr(void)
{
if (tx_counter)
{
--tx_counter;
UDR=tx_buffer[tx_rd_index];
if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
};
}
#ifndef _DEBUG_TERMINAL_IO_
// Write a character to the USART Transmitter buffer
#define _ALTERNATE_PUTCHAR_
#pragma used+
// Standard Input/Output functions
void putchar(char c)
{
while (tx_counter == TX_BUFFER_SIZE);
#asm("cli")
if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
{
tx_buffer[tx_wr_index]=c;
if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
++tx_counter;
}
else
UDR=c;
#asm("sei")
}
#pragma used-
#endif
/*******************************************************************/
uchar ds18b20_devices;
//number of DS1820 devices connected to the 1 Wire bus
uchar rom_code[MAX_DEVICES][9]; //DS18B20 devices ROM code storage area
uchar num1,num2,num3,num4;
uchar numds1,numds2,numds3,numds4; //4bit 7segment code number;
uchar DS1,DS2,tmpd1,tmpd2,num_devices;
void DSPDATA(uchar DSCMD, uchar DSDATA1, uchar DSDATA2);
void DSPCMD(uchar CMD);
void DS18B20_cfg(void);
//Search DS18B20 Device and Configure each DS18B20 device;
void measure_temp(void);
void float_7seg(float number);
void putchar(char c);
/****************************************************************/
void main(void)
{
SREG.7=0; //Global disable interrupts
PORTC=0x00;
DDRC=0x15;
MCUCR=0x00;
EMCUCR=0x00;
UCSRA=0x00;
UCSRB=0x48;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x19;
CLK=0;
DATA=0;
ENA=1;
WDTCR=0x1B;
WDTCR=0x0B;
SREG.7=1;
// w1_init(); // 1 Wire Bus initialization
// DS18B20_cfg(); // DS18B20 Config
while(1)
{
#asm
WDR
#endasm
#asm("sei")
/*****************************************************
这一段18B20加载的,目前放在循环里,原来是在循环上面的。不知道怎么回事,
用在M8515上如果在工作时增加或减少18B20时,会出现乱码,而用在M168上时就
不会出现这个现象。
***********************************************************************/
w1_init(); // 1 Wire Bus initialization
DS18B20_cfg(); // DS18B20 Config
/********************************************************************/
if(ds18b20_devices==0)
{
DSPCMD(0xff);
DSPDATA(0x86,0x7d,0x00);
}
else
{
measure_temp();
}
}
}
void float_7seg(float number)
//float number converter to 4 bit 7segment number
{
uchar k1;
k1=number;
num4=(number-k1)*10;
num3=(k1%10);
k1=k1/10;
num2=k1%10;
num1=k1/10;
}
//----------------------------------------------------------------------------------------------------------
void DS18B20_cfg(void)
//Search DS18B20 Device and Configure each DS18B20 device;
{
uchar i;
// detect how many DS18B20 devices are connected to the 1 Wire bus
ds18b20_devices=w1_search(DS18B20_SEARCH_ROM_CMD,rom_code);
// configure each DS18B20 device for 12 bit temperature measurement resolution
for (i=0;i<ds18b20_devices;)
ds18b20_init(&rom_code[i++][0],20,30,DS18B20_12BIT_RES);
}
void measure_temp(void)
{
uchar i,j;
float n;
if(ds18b20_devices)
for (i=0;i<ds18b20_devices;i++)
{
n=ds18b20_temperature(&rom_code[0]);
float_7seg(n);
numds1=num1;
numds2=num2;
numds3=num3;
numds4=num4;
num4&=0x0f;
num3=num3<<4;
num3&=0xf0;
DS2=num3|num4;
num2&=0x0f;
num1=num1<<4;
num1&=0xf0;
DS1=num1|num2;
//每个温度值显示时指明是第几个18B20;
j=i+1;
j=0x0f&j;
num_devices=0x00|j;
num_devices=num_devices|0xa0;
// MC14489驱动数码管显示;
DSPCMD(0x91);
DSPDATA(num_devices,DS1,DS2);
delay_ms(100);
numds2=numds2<<4;
numds2&=0xf0;
numds3&=0x0f;
tmpd1=numds2|numds3;
numds1=numds4<<4;
numds1&=0xf0;
tmpd2=numds1|0x0c;
printf("TEMP%2x:%2x.%2x\n\r",num_devices,tmpd1,tmpd2);// TO PC,RS232;
}
}
/*************MC14489驱动代码************************************/
void DSPCMD(uchar CMD)
{ //单字节命令函数, 写入MC14489内部设置寄存器
uchar i;
ENA=0; // 使能MC14489
for (i=8;i>=1;i--) { // 写入单字节命令
DATA=CMD&0x80;
CMD=CMD<<1;
CLK=0;
CLK=1;
}
ENA=1; // 禁止MC14489
}
void DSPDATA(uchar DSCMD, uchar DSDATA1, uchar DSDATA2)
{
uchar DSP,i,j; // 多字节命令函数, 写入MC14489显示寄存器
i=0;
ENA=0; // 使能MC14489
while(i<24) { // 写入三字节显示数据
if(i<8) {DSP=DSCMD;}
else if(i<16) {DSP=DSDATA1;}
else {DSP=DSDATA2;}
for(j=8;j>=1;j--) {
DATA=DSP&0x80;
DSP=DSP<<1;
CLK=0;
CLK=1;
}
i=i+8;
}
ENA=1; //禁止MC14489
} |
|