#ifndef __DS18B20_H__
#define __DS18B20_H__
#include <mega16.h>
#include <stdint.h>
#define DQ_DDR_IN() DDRB.5 = 0 // PB5引脚设置为输入
#define DQ_DDR_OUT() DDRB.5 = 1 // 设置为输出
#define DQ_SET() PORTB.5 = 1 // 输出1
#define DQ_RESET() PORTB.5 = 0 // 输出0
#define DQ_WRITE(x) PORTB.5 = (x) // 输出x
#define DQ_DATA PINB.5 // 读取端口
uint8_t ds18b20_init(void);
uint16_t read_temperature(void);
void read_temp_init(void);
#endif
#include <delay.h>
#include "ds18b20.h"
// 初始化DS18B20传感器
uint8_t ds18b20_init(void) {
uint8_t is_high = 0;
// 设置DQ引脚为输出
DQ_DDR_OUT();
// 发送复位脉冲
DQ_SET();
delay_us(5);
DQ_RESET();
delay_us(500);
DQ_SET();
// 切换DQ引脚为输入
DQ_DDR_IN();
// 等待DS18B20的响应
delay_us(70);
is_high = DQ_DATA;
delay_us(500);
return is_high;
}
// 向DS18B20写入一个字节的数据
void write_ds18b20(uint8_t value) {
uint8_t i;
DQ_DDR_OUT();
for (i = 0; i < 8; i++) {
// 发送写时序
DQ_RESET();
delay_us(10);
// 写入数据位
DQ_WRITE((value & (1 << i)) > 0);
delay_us(60);
DQ_SET();
delay_us(10);
}
}
// 从DS18B20读取一个字节的数据
uint8_t read_ds18b20(void) {
uint8_t i;
uint8_t value = 0;
for (i = 0; i < 8; i++) {
// 发送读时序
DQ_DDR_OUT();
DQ_RESET();
delay_us(5);
DQ_SET();
delay_us(5);
// 切换DQ引脚为输入
DQ_DDR_IN();
// 读取数据位
value |= (DQ_DATA << i);
delay_us(70);
}
return value;
}
// 读取DS18B20传感器的温度值
uint16_t read_temperature(void) {
uint8_t data_h, data_l;
// 关中断
#asm("cli")
// 初始化DS18B20传感器
while (ds18b20_init()) {};
// 发送跳过ROM命令
write_ds18b20(0xCC);
// 发送温度转换命令
write_ds18b20(0x44);
// 初始化DS18B20传感器
while (ds18b20_init()) {};
// 发送跳过ROM命令
write_ds18b20(0xCC);
// 发送读取温度命令
write_ds18b20(0xBE);
// 读取温度数据低字节
data_l = read_ds18b20();
// 读取温度数据高字节
data_h = read_ds18b20();
// 开中断
#asm("sei")
// 计算温度值并返回
return ((data_h & 0x0F) << 4 | (data_l >> 4)) * 100 + (data_l & 0x0F) * 625 / 100;
}
void read_temp_init(void) {
#asm("cli")
// 初始化DS18B20传感器
ds18b20_init();
// 发送跳过ROM命令
write_ds18b20(0xCC);
// 发送温度转换命令
write_ds18b20(0x44);
// 开中断
#asm("sei")
delay_ms(800);
}
#ifndef __SHOW_SEG_H
#define __SHOW_SEG_H
#include <mega16.h>
#include <stdint.h>
#define SEG_PORT PORTA //IO口宏定义
#define SEG_DDR DDRA
#define SEG_NUM 8
#define SEG_MAX_NUM 8
#define LE_PORT_BIT PORTD.0
#define LE_PORT_DDR DDRD.0
#define SEG_U 16
#define SEG_F 15
#define SEG_C 12
#define SEG_H 18
#define SEG_P 19
#define SEG_BAR 17
void seg_init(void);
void seg_show(void);
extern uint8_t seg_en[SEG_NUM];
extern uint8_t seg_num[SEG_NUM];
extern uint8_t seg_point[SEG_NUM];
#endif
#include <mega16.h>
#include <stdint.h>
#include <delay.h>
#include "show_seg.h"
//段码 0,1,2,3,4,5,6,7,8,9,A,b,C,d,E,F,U,-,H,P
flash char seg_code[20] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x3E, 0x40, 0x76, 0x73};
uint8_t seg_en[SEG_NUM]; //数码管使能标志位
uint8_t seg_num[SEG_NUM]; //存放每个数码管要显示的东西
uint8_t seg_point[SEG_NUM]; //数码管小数点显示使能标志位
uint8_t seg_flag;
//数码管初始化函数,默认数码管全部关闭
void seg_init(void) {
SEG_DDR = 0xFF;
SEG_PORT = 0x00;
LE_PORT_DDR = 0x01;
LE_PORT_BIT = 0x01;
LE_PORT_BIT = 0x00;
}
void seg_show(void) {
SEG_PORT = 0; //数码管显示全部清零
LE_PORT_BIT = 0x01;
LE_PORT_BIT = 0x00;
SEG_PORT = ~(seg_en[seg_flag] << seg_flag); //给每一位数码管传入使能数据
LE_PORT_BIT = 0x01; //锁存器使能
LE_PORT_BIT = 0x00;
// SEG_PORT = 0;
SEG_PORT = seg_code[seg_num[seg_flag]] | (seg_point[seg_flag] << 7);//传入段码
seg_flag = (seg_flag + 1) % 8;
}
#ifndef __EEPROM_H__
#define __EEPROM_H__
#define E_WRITE_ADDR 0xA0 // 写地址
#define E_READ_ADDR 0xA1 // 读地址
void EEPROM_write(uint8_t addr, uint8_t data);
uint8_t EEPROM_read(uint8_t addr);
#endif
#include <stdint.h>
#include "I2C.h"
#include "EEPROM.h"
// 向EEPROM写入一个字节的数据
void EEPROM_write(uint8_t addr, uint8_t data) {
// 发送起始信号
IIC_start();
// 发送EEPROM写入地址
IIC_write(E_WRITE_ADDR);
IIC_read_act();
// 发送EEPROM内存地址
IIC_write(addr);
IIC_read_act();
// 发送要写入的数据
IIC_write(data);
IIC_read_act();
// 发送停止信号
IIC_stop();
}
// 从EEPROM读取一个字节的数据
uint8_t EEPROM_read(uint8_t addr) {
uint8_t data = 0;
// 发送起始信号
IIC_start();
// 发送EEPROM写入地址
IIC_write(E_WRITE_ADDR);
IIC_read_act();
// 发送EEPROM内存地址
IIC_write(addr);
IIC_read_act();
// 发送起始信号(切换到读模式)
IIC_start();
// 发送EEPROM读取地址
IIC_write(E_READ_ADDR);
IIC_read_act();
// 读取数据
data = IIC_read();
// 发送非应答信号
IIC_write_act(1);
// 发送停止信号
IIC_stop();
return data;
}
#ifndef __I2C_H__
#define __I2C_H__
#include <stdint.h>
#include <mega16.h>
#include <delay.h>
#define SCL_DDR DDRB.3
#define SDA_DDR DDRB.4
#define SCL_PORT PORTB.3
#define SDA_PORT PORTB.4
#define SCL_PIN PINB.3
#define SDA_PIN PINB.4
#define SCL_OUT() SCL_DDR = 1
#define SCL_IN() SCL_DDR = 0
#define SDA_OUT() SDA_DDR = 1
#define SDA_IN() SDA_DDR = 0
#define SCL_SET() SCL_PORT = 1; delay_ms(1);
#define SCL_RESET() SCL_PORT = 0; delay_ms(1);
#define SCL_WRITE(x) SCL_PORT = (x); delay_ms(1);
#define SDA_SET() SDA_PORT = 1; delay_ms(1);
#define SDA_RESET() SDA_PORT = 0; delay_ms(1);
#define SDA_WRITE(x) SDA_PORT = (x); delay_ms(1);
#define SCL_DATA() SCL_PIN
#define SDA_DATA() SDA_PIN
void IIC_init(void);
void IIC_start(void);
void IIC_stop(void);
void IIC_write(uint8_t data);
uint8_t IIC_read(void);
void IIC_write_act(uint8_t act);
uint8_t IIC_read_act(void);
#endif
#include <stdint.h>
#include "I2C.h"
// 初始化I2C总线
void IIC_init(void) {
SCL_OUT();
SDA_OUT();
SCL_SET();
SDA_SET();
}
// 发送I2C起始信号
void IIC_start(void) {
SDA_SET();
SCL_SET();
SDA_RESET();
SCL_RESET();
}
// 发送I2C停止信号
void IIC_stop(void) {
SDA_RESET();
SCL_SET();
SDA_SET();
}
// 向I2C总线写入一个字节的数据
void IIC_write(uint8_t data) {
uint8_t i;
for (i = 0; i < 8; i++) {
SDA_WRITE(data & (0x80 >> i));
SCL_SET();
SCL_RESET();
}
SDA_RESET();
}
// 从I2C总线读取一个字节的数据
uint8_t IIC_read(void) {
uint8_t i;
uint8_t data = 0;
SDA_IN();
for (i = 0; i < 8; i++) {
SCL_SET();
data |= (SDA_DATA() << (7 - i));
SCL_RESET();
}
SDA_OUT();
return data;
}
// 向I2C总线写入一个动作(活动)信号
void IIC_write_act(uint8_t act) {
SDA_WRITE(act);
SCL_SET();
SCL_RESET();
}
// 从I2C总线读取一个动作(活动)信号
uint8_t IIC_read_act(void) {
uint8_t act = 0;
SDA_SET();
SCL_SET();
SDA_IN();
act = SDA_DATA();
SDA_OUT();
SCL_RESET();
return act;
}
#ifndef __KEY_H__
#define __KEY_H__
#include <mega16.h>
#include <stdint.h>
#define KEY1_PORT PORTC.4 //IO口宏定义
#define KEY2_PORT PORTC.5
#define KEY3_PORT PORTC.6
#define KEY4_PORT PORTC.7
#define KEY1_PIN PINC.4
#define KEY2_PIN PINC.5
#define KEY3_PIN PINC.6
#define KEY4_PIN PINC.7
#define KEY1_DDR DDRC.4
#define KEY2_DDR DDRC.5
#define KEY3_DDR DDRC.6
#define KEY4_DDR DDRC.7
//按键名字宏定义
enum {
KEY1, KEY2, KEY3, KEY4
};
void key_init(void);
void refresh_key(void);
uint8_t key_is_down(uint8_t key_num);
uint8_t key_is_down_long(uint8_t key_num);
#endif
#include <mega16.h>
#include <stdint.h>
#include "key.h"
uint8_t key_state[4][2];//按键状态,分为按下和断开,其中每个状态记录两次,即前一次和当前
uint8_t key_down[4];
uint8_t key_down_long[4];
#define I_KEY(x) x##_DDR = 0; \
x##_PORT = 1;
//按键初始化函数
void key_init(void) {
I_KEY(KEY1);//输入设为上拉模式
I_KEY(KEY2);
I_KEY(KEY3);
I_KEY(KEY4);
}
//刷新按键状态,记录上一次状态同时获取当前状态,如果前一次为按下当前为松开则表示按键单击了一次
#define R_KEY(x) key_state[x][0] = key_state[x][1]; \
key_state[x][1] = !x##_PIN; \
key_down[x] = (key_state[x][1] == 0) && (key_state[x][0] == 1);
//刷新按键状态函数
void refresh_key(void) {
R_KEY(KEY1);
R_KEY(KEY2);
R_KEY(KEY3);
R_KEY(KEY4);
}
//判断按键是否按下函数
uint8_t key_is_down(uint8_t key_num) {
uint8_t key_value = key_down[key_num];
key_down[key_num] = 0;
return key_value;
}
// 按键长按
uint8_t key_is_down_long(uint8_t key_num) {
uint8_t key_value = key_down[key_num] && (key_down_long[key_num] >= 10);
if (key_value) {
key_down[key_num] = 0;
key_down_long[key_num] = 0;
}
return key_value;
}
#ifndef __LED_H__
#define __LED_H__
#define LED1_PORT PORTD.3
#define LED2_PORT PORTD.4
#define LED3_PORT PORTD.5
#define LED4_PORT PORTD.6
#define LED5_PORT PORTD.7
#define LED1_DDR DDRD.3
#define LED2_DDR DDRD.4
#define LED3_DDR DDRD.5
#define LED4_DDR DDRD.6
#define LED5_DDR DDRD.7
#define SET_LED(x) x##_PORT = 1
#define RESET_LED(x) x##_PORT = 0
#define WRITE_LED(x, n) x##_PORT = (n)
void led_init(void);
#endif
#include <mega16.h>
#include "led.h"
#define I_LED(x) x##_DDR = 1; \
x##_PORT = 0;
void led_init(void) {
I_LED(LED1);
I_LED(LED2);
I_LED(LED3);
I_LED(LED4);
I_LED(LED5);
}
#ifndef __PCF8591_H__
#define __PCF8591_H__
#define P_WRITE_ADDR 0x90 // 写地址
#define P_READ_ADDR 0x91 // 读地址
#define VOL4 0xCD // 4V
#define VOL2 0x67 // 2V
#define VOL04 0x15 // 0.4V
void write_vol(uint8_t vol);
float Pcf8591ReadVol(uint8_t channel);
#endif
#include <stdint.h>
#include "I2C.h"
#include "pcf8591.h"
// 向PCF8591写入电压值
void write_vol(uint8_t vol) {
// 发送起始信号
IIC_start();
// 发送PCF8591写入地址
IIC_write(P_WRITE_ADDR);
IIC_read_act();
// 发送PCF8591控制字节
IIC_write(0x40);
IIC_read_act();
// 发送电压值
IIC_write(vol);
IIC_read_act();
// 发送停止信号
IIC_stop();
}
//pcf读取通道输入函数
float Pcf8591ReadVol(uint8_t channel)
{
uint8_t num;
float value;
IIC_start();//发送开始信号
IIC_write(P_WRITE_ADDR);//写入控制字节让pcf处于ad模式
IIC_write(0x40 | channel);
IIC_stop();
IIC_start();
IIC_write(P_READ_ADDR); //发送读地址
num=IIC_read(); //读取数据
IIC_stop(); //结束总线
value = num * 0.01953; //读取到的值为0-255,除51才是实际的值
return value;
}