文档库 最新最全的文档下载
当前位置:文档库 › ATTiny13

ATTiny13

/**
* @file : main.c
*
* Copyright (c) : 2003-2010, Hyper Studio
*
* @brief :
*
*
* @version : 1.01 (CVS revision : 1.0)
*
* @date
* -# 创建时间 : 2010/8/19
* -# 修改时间 : 2010/9/30
*
* @author
* -# 创建人 : xiecf
* -# 修改人 : xiecf
*
* @其他说明 :一个TAB=4个空格
*****************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include "./headerFiles/typedefine.h"
#include "./headerFiles/macDefine.h"

/**
函数名称 : int0Handler

功能描述 : 延时

输 入 : 无

输 出 :


返回 :无

全局变量 :

调用模块 :

警告 :
*****************************************************************************/

volatile uint8 recvFlag = USART_RECEIVE_DISABLE;
volatile uint8 int0Flag = INT0_VALUABLE;
/* 通过配置workingTime来配置芯片每次连续工作的时间 */
volatile uint8 workingTime=0;
SIGNAL(INT0_vect)
{
/* 相当于复位看门狗 */
workingTime = 0;
if(int0Flag == INT0_VALUABLE)
{
/* 关闭INT0 中断 */
GIMSK = 0x00;
recvFlag = USART_RECEIVE_ENABLE;
/* 清除中断标志*/
TIFR0 |= 1</* 设置计数器,这会影响发送,但是概率很小 */
TCNT0 = 15;
int0Flag = INT0_INVALUABLE;
}
}


/**
函数名称 : timerCpbHandler

功能描述 : 串口输出功能

输 入 : 无

输 出 :


返回 :无

全局变量 :

调用模块 :

警告 :
*****************************************************************************/
volatile uint8 sendChar = 'A';
volatile uint8 usartCtr = USART_SEND_DISABLE;
uint8 sendBitMask = USART_START_BIT;
/* 控制停止位的长度 */
uint8 stopBitNum = 0;
SIGNAL(TIM0_COMPB_vect)
{
if(usartCtr == USART_SEND_ENABLE)
{
/* 发送起始位 */
if(sendBitMask == USART_START_BIT)
{
sendBitMask = 0x01;
PORTB &= ~(1<stopBitNum = 0;
}
else
{
if(sendBitMask == USART_STOP_BIT)
{
/* 发送停止位 */
if(stopBitNum >= STOP_BIT_LENTH)
{
stopBitNum = 0;
sendBitMask = USART_START_BIT;
usartCtr = USART_SEND_DISABLE;
}
else
{
PORTB |= (1<}
stopBitNum++;
}
else
{
if(sendChar&sendBitMask)
{
/* 根据实际电路决定是否取反 */
PORTB |= (1<}
else
{
PORTB &= ~(1<}
sendBitMask <<= 1;
if (sendBitMask == USART_START_BIT)
{
sendBitMask = USART_STOP_BIT;
}
}
}
}
}

/**
函数名称 : timerCpaHandler

功能描述 : 从

串口接收数据

输 入 : 无

输 出 :


返回 :无

全局变量 :

调用模块 :

警告 :
*****************************************************************************/
volatile uint8 recvBuf[2] = {'x', 'y'};
uint8 recvBitMask = 0x01;
uint8 recvChar = 'r';
uint8 recvBitCnt = 0;
uint8 recvIndex = 0;
volatile uint8 recvBufFlag = RECEIVE_BUF_EMPTY;
SIGNAL(TIM0_COMPA_vect)
{
if(recvFlag == USART_RECEIVE_ENABLE)
{
recvBitCnt++;
/* 不采样起始位,并且错开半个周期 */
if (recvBitCnt >= 2)
{
if(PINB & (1<{
/* 根据实际电路决定是否要反向 */
recvChar |= recvBitMask;
}
else
{
recvChar &= ~recvBitMask;
}
recvBitMask <<= 1;
/* 接收到一个完整字符,rcvBitCnt!=10是避免重复赋值 */
if(recvBitMask == 0 && recvBitCnt!=10)
{
recvBuf[recvIndex] = recvChar;
recvIndex++;
if(recvIndex >= 2)
{
recvIndex = 0;
recvBufFlag = RECEIVE_BUF_FULL;
}
if(recvChar == 'e')
{
recvIndex = 0;
}
}
}
/* 把停止位包括在内,否则低电平中断又会产生,产生错误接收 */
if(recvBitCnt>=10)
{
recvBitMask = 0x01;
recvFlag = USART_RECEIVE_DISABLE;
recvBitCnt = 0;
int0Flag = INT0_VALUABLE;
/* 开启INT0中断 */
GIMSK = 0x40;
}
}
}

/**
函数名称 : watchDogOverHandler

功能描述 : 看门狗,暂时作为通用计数器使用

输 入 :

输 出 :


返回 :无

全局变量 :

调用模块 :

警告 :
*****************************************************************************/

//uint8 ledFlag = 1;
SIGNAL(WDT_vect)
{
workingTime++;
/*
//调试用代码
if(ledFlag == 1)
{
PORTB |= 1<ledFlag = 0;
}
else
{
PORTB &= ~(1<ledFlag = 1;
}
*/
/* 在看门狗配置为每8s溢出一次是,workingTime >= 75表示连续工作10分钟 */
if(workingTime >=75)
{
workingTime = 0;
__asm__ __volatile__ ("wdr");
WDTCR |= (1</* 关闭看门狗 */
WDTCR = 0x00;
/* 使看门狗能够在INT0中重启 */
int0Flag = INT0_VALUABLE;

/* 睡眠前一定要让电池空载,阅读原理图应该是置低*/
PORTB &= ~(1</* 开全局中断,否则无法被INT0唤醒 */
SREG = 0x80;
/* 省电模式 */
MCUCR |= (1<__asm__ __volatile__ ("sleep");

WDTCR |= (1</* 关闭看门狗 */
WDTCR = 0x46;
}
}


/**
函数名称 : sendString

功能描述 : 经过二次封装的串口发送

输 入 :

输 出 :


返回 :无

全局变量 : usartCtr

调用模块 :

警告 :
*****************************************************************

************/

void sendString(uint8 *dataBuf, uint8 len)
{
uint8 i;
for(i=0; i{
while(usartCtr == USART_SEND_ENABLE);
sendChar = *(dataBuf+i);
usartCtr = USART_SEND_ENABLE;
}
}

/**
函数名称 : adcCompleteHandler

功能描述 : ADC转换结束中断处理函数

输 入 :

输 出 :


返回 :无

全局变量 :

调用模块 :

警告 :
*****************************************************************************/
/* 经过实际验证,adc[8]不能改成adc[16],可能的原因应该是造成主程序中的栈溢出 */
volatile uint16 adc[8];
uint8 adcCnt = 0;
SIGNAL(ADC_vect)
{
uint16 tmpADCHL;
uint16 tmpADCH;
tmpADCHL = ADCL;
tmpADCH = ADCH;
tmpADCHL |= tmpADCH<<8;
adc[adcCnt] = tmpADCHL;
adcCnt++;
if(adcCnt>=8)
{
adcCnt = 0;
}
}

/*0x55(高字节), 0xfefe是特意安排的返回给主设备的结束符 */
uint16 backCmd[4] = {0x5500,0x00, 0x7856, 0xfefe};
int main(void)
{
uint8 i;
uint8 id;
uint16 filterAdc;
/* 配置IO */
/* PB0和PB2配置为输出 */
DDRB = 0x05;
/* 因为PORTB1配置为输入,作为串口的RX脚使用,这里配置成内部上拉 */
/* PORTB |= (1</* 将TX脚(PB0),初始化为高电平,串口进入空闲状态 */
/* PORTB |= 1</* 初始化时应该让电池空载,阅读原理图应该是置底PB2 */
/* PORTB &= ~(1<PORTB = 0x03;

/* TC0工作在CTC 模式 */
TCCR0A |= 1</* OCR0A=31是为了产生为4800的波特率,这与计算有点偏差,31是实际测试的结果 */
OCR0A = 31;
OCR0B = 31;
/* 中断比较匹配OCR0A使能(用来串口接收),比较匹配OCR0B中断使能(串口发送) */
TIMSK0 |= 1</* 开定时器,系统时钟9.6M,再64分频(注意:不是系统8分频) */
TCCR0B |= 1<
/* 配置PORTB1的上低电平触发异步中断,因为面板板的ULN2003A反了向,时间情况应该是原理图定*/
// MCUCR |= (1</* 开启INT0 中断 */
GIMSK = 0x40;


/* 配置看门狗,暂时作为通用计数器使用 */
/* 清除MCUSR寄存器中的WDRF */
MCUSR = 0;
/* 根据数据手册(一定要以英文的为准)的时序,无法合并 */
WDTCR |= (1</* 中断模式 WDTON=1,WDE=0; TDTIE=1,溢出周期1s */
WDTCR = 0x46;

/* 配置ADC */
/* 参考电压为VCC,转换结果右对齐,复位后默认采样PB3引脚上电池的电压 */
ADMUX |= 1</* 连续转换,这也是复位后的默认设置 */
ADCSRB = 0;
/* 为降低功耗而禁用这两个引脚的数字输入缓冲 */
DIDR0 = 0x18;
/* 使能ADC,同时启动转换,自动清除中断标志,

中断使能,128预分频,分频大一点是想中断不要太频繁而影响串口 */
ADCSRA = 0xff;

/* 将存储在EEPROM中的ID读取出来 */
EEARL = 0;
/* 这时尚未开全局中断 */
EECR |= (1<id = EEDR;

/* 开全局中断 */
SREG = 0x80;
while(1)
{
if(recvBufFlag == RECEIVE_BUF_FULL)
{
if(recvBuf[1] == id)
{
/* 返回温度值 */
if(recvBuf[0] == 't')
{
/* 参考电压为VCC,转换结果右对齐,切换到采样PB3引脚上的温度 */
ADMUX |= (1<}
/* 返回空载电压值 */
if(recvBuf[0] == 'v')
{
/* 切换ADC电压通道PB4到采样电池电压 */
ADMUX &= ~(1</* 置高还是置底需要根据实际电路决定,通过阅读原理图应该是低表示空载 */
PORTB &= ~(1<}
/* 返回标准负载载电压值 */
if(recvBuf[0] == 'l')
{
/* 切换ADC电压通道PB4到采样电池电压,通过阅读原理图应该是高表示带载 */
ADMUX = (1</* 置高还是置底需要根据实际电路决定 */
PORTB |= (1<}
filterAdc = 0;
/* 先把ADC转换完成中断禁用,避免计算过程中半截数据被意外修改 */
ADCSRA = 0xf7;
for(i=0; i<8; i++)
{
filterAdc += adc[i];
}


/* 开启中断,其他配置不变:使能ADC,同时启动转换,清除中断,128预分频,分频大一点是想中断不要太频繁而影响串口 */
ADCSRA = 0xff;
/* 滑动滤波,取均值 */
filterAdc >>= 3;
/* 返回相关的命令,这样主设备可以验证数据是否可信 */
*((uint8*)&backCmd[0]) = recvBuf[0];
*((uint8*)backCmd+1) = id;
backCmd[1] = filterAdc;
backCmd[2] = filterAdc;
sendString((uint8*)backCmd, 8);

}
if(recvBuf[0] == 'i')
{
/* 临时置高, 以便于判断是否要修改ID,刚置低后立即读引脚是达不到效果的*/
PORTB |= (1<EEARL = 0;
EEDR = recvBuf[1];
if(!(PINB & 1<{
/* 为了确保写EEPROM有正确的时序,关闭全局中断 */
SREG &= ~(1<<7);
/* 按照数据手册说明两句不能合并,因为有一个先后顺序 */
EECR |= (1<EECR |= (1</* 开全局中断 */
SREG |= (1<<7);
}
/* PB2置底,将电池切换到空载的情况 */
PORTB &= ~(1<}
/* 空间不够,省去返回值,并且也应该省去,否则会出现总线冲突 */
/* 置串口数据无效,表明接收到的数据已经被使用过了 */
recvBufFlag = RECEIVE_BUF_EMPTY;
}
}
}


相关文档