测试使用的MCU 型号
- STC15F104W
- 内部架构
传感器型简介
传感器原理图
TSIC506 主驱动代码
// ------------------config.h---------------------
#ifndef __CONFIG_H
#define __CONFIG_H
#include "STC15Fxxxx.H"
//#define MAIN_Fosc 5529600L //定义主时钟 110 ~ 4800
#define MAIN_Fosc 11059200L //定义主时钟 110 ~ 9600
//#define MAIN_Fosc 12000000L //定义主时钟 110 ~ 9600
//#define MAIN_Fosc 22118400L //定义主时钟 220 ~ 19200
//#define MAIN_Fosc 24000000L //定义主时钟 220 ~ 19200
//#define MAIN_Fosc 33177600L //定义主时钟 220 ~ 38400
// 数据类型定义
typedef bit BOOL;
typedef unsigned char uchar;
typedef unsigned int uint;
#define TRUE 1
#define FALSE 0
#define Main_Fosc_KHZ (MAIN_Fosc / 1000)
#endif
- tsic506.h 文件:声明tsic506外部公开的函数
// ------------------tsic506.h---------------------
#ifndef __TSIC506_H
#define __TSIC506_H
#include "config.h"
sbit DQ = P3^3;
BOOL tsic506_init(void); // 模块初始化函数
BOOL Check_Parity(uint value);
uint read_byte(void);
BOOL getTSIC_Temp (uint *temp_value16);
#endif /* __TSIC506_H */
- tsic506.c 文件:定义tsic06相关驱动代码
// ------------------tsic506.c---------------------
#include <tsic506.h>
#include <delay.h>
// 初始化函数
BOOL tsic506_init()
{
DQ = 1;
while(!DQ);
return TRUE;
}
// 读取一次总线上的数据
uint read_byte(void)
{
uchar i;
uint temp_value = 0;
// 等待开始信号
while(DQ == 1); // 等待总线被从机拉低
while(DQ == 0); // 等待就绪
// 在下降沿读取8位数据+1位奇偶校验位
for (i = 0; i < 9; i++)
{
while(DQ == 1); // 等待下降沿产生,以读取总线
delay_5us(12);
if (DQ == 1)
{
temp_value |= 1 << (8-i); // 取一个位,从高位开始存
}
else
{
while(DQ == 0); // 等待总线再次拉高,便于下次产生下降沿
}
}
return temp_value;
}
// 检查校验位是否为1
BOOL Check_Parity(uint value)
{
uchar i;
uchar parity = 0;
for (i = 0; i < 9; i++)
{
if (value & (1 << i))
{
parity++;
}
}
if (parity % 2)
{
return FALSE;
}
return TRUE;
}
// 获取温度
BOOL getTSIC_Temp (uint *temp_value16)
{
uint temp_value1 = 0;
uint temp_value2 = 0;
uint Temperature;
temp_value1 = read_byte();
temp_value2 = read_byte();
// 校验温度数据高字节
while(!Check_Parity(temp_value1))
{
return FALSE;
}
// 校验温度数据低字节
while(!Check_Parity(temp_value2))
{
return FALSE;
}
// 删除校验位
temp_value1 >>= 1;
temp_value2 >>= 1;
Temperature = (temp_value1 << 8) | temp_value2;
*temp_value16 = Temperature;
return TRUE;
}
// 头文件内容
#ifndef __DELAY_H
#define __DELAY_H
#include "config.h"
#define MS_STEP (Main_Fosc_KHZ / 14)
void delay_ms(unsigned int ms);
void delay_5us(uchar step); /* 11.0592M晶振,1T单片机 */
#endif /* __DELAY_H */
//////////////////////////////////////////////////////////////////////
// C文件内容
#include <delay.h>
/*
* @brief:自适应毫秒延时函数,理论定时范围1~65535
*/
void delay_ms(unsigned int ms)
{
unsigned int i;
do{
i = MS_STEP;
while(--i); // 14T per loop
}while(--ms);
}
/* 1T单片机,主频11.0592M,延时函数,延时10us */
void delay_5us(uchar step) // 误差 -0.053530092593us
{
unsigned char a;
while(step-- > 0)
{
for(a=1;a>0;a--);
}
}
#include <uart.h>
#include <delay.h>
#include <tsic506.h>
void main()
{
uint temp_value;
float Temp_float;
uart_init(); // UART模块的初始变量
tsic506_init();
while(1)
{
if(getTSIC_Temp(&temp_value))
{
Temp_float = ((float)temp_value / 2047 * 70) - 10;
printf("%.2f
",Temp_float);
}
}
}
STC15F104W虚拟串口代码实现
- 由于STC15F104W单片机内部并没有串口外设,故需要自己模拟串口,具体原理可以参考数据手册,这里就不赘述了。
- uart源文件uart.c
#include <uart.h>
uchar data TBUF = 0, RBUF = 0;
uchar data TDAT = 0, RDAT = 0;
uchar data TCNT = 0, RCNT = 0; // 发送和接收检测 计数器(3倍速率检测)
uchar data TBIT = 0, RBIT = 0; // 发送和接收的数据计数器
uchar data t = 0, r = 0;
uchar data Rev_buf[BUFF_SIZE] = "0";
uchar data S_BUF; // 用于接收串口一个字节的返回值
bit flag = 0; // 用于标志是否有数据到来
bit TING, RING; // 正在发送或接收一个字节
bit TEND, REND; // 接收或发送完成的标志位
// UART模块的初始变量 initial UART module variable
void uart_init()
{
InternalRAM_enable();
Timer0_1T();
Timer0_AsTimer();
Timer0_16bitAutoReload(); // 设置定时器0位16位自动重装模式
Timer0_Load(Timer0_Reload);
Timer0_InterruptEnable();
Timer0_Run();
EA = 1;
TING = 0;
RING = 0;
REND = 0;
TEND = 1;
TCNT = 0;
RCNT = 0;
}
void uart_send(uchar dat) // 串口发送一个字节函数
{
if(TEND)
{
TEND = 0;
TBUF = dat;
TING = 1;
while(!TEND);
}
}
uchar uart_receive(void) // 接收函数
{
if (REND) // 如果接收完,把接收到的值存入接收S_BUF
{
REND = 0;
if(r < BUFF_SIZE) Rev_buf[r++] = RBUF;
else r = 0;
S_BUF = RBUF;
flag = 1;
}
return S_BUF;
}
// 重定向printf,需要重写putchar函数;当包含 stdio.h 头文件时,可以直接和标准C一样使用printf进行格式化输出。
char putchar(char c)
{
uart_send(c);
return c;
}
// 发送一串字符串
void uart_printf(uchar * p_buf)
{
while(*p_buf != ' ')
{
uart_send(*p_buf);
p_buf++;
}
}
// 定时器0中断程序for UART 以波特率3倍的速度采样判断 开始位 Timer interrupt routine for UART
void tm0(void) interrupt 1 using 1
{
if (RING)
{
if (--RCNT == 0) // 接收数据以定时器的1/3来接收
{
RCNT = 3; // 重置接收计数器 接收数据以定时器的1/3来接收 reset send baudrate counter
if (--RBIT == 0) // 接收完一帧数据
{
RBUF = RDAT; // 存储数据到缓冲区 save the data to RBUF
RING = 0; // 停止接收 stop receive
REND = 1; // 接收完成标志设置 set receive completed flag
}
else
{
RDAT >>= 1; // 把接收的单b数据 暂存到 RDAT(接收缓冲)
if (RXB) RDAT |= 0x80; // shift RX data to RX buffer
}
}
}
else if (!RXB) // 判断是不是开始位 RXB=0;
{
RING = 1; // 如果是则设置开始接收标志位 set start receive flag
RCNT = 4; // 初始化接收波特率计数器 initial receive baudrate counter
RBIT = RxBitLenth; // 初始化接收的数据位数(8个数据位+1个停止位) initial receive bit number (8 data bits + 1 stop bit)
}
if (--TCNT == 0) // 发送数据以定时器的1/3来发送
{
TCNT = 3; // 重置发送计数器 reset send baudrate counter
if(TING)
{
if (TBIT == 0) // 发送计数器为0 表明单字节发送还没开始
{
TXB = 0; // 发送开始位 send start bit
TDAT = TBUF; // 把缓冲的数据放到发送的buff load data from TBUF to TDAT
TBIT = TxBitLenth; // 发送数据位数 (8数据位+1停止位) initial send bit number (8 data bits + 1 stop bit)
}
else // 发送计数器为非0 正在发送数据
{
TDAT >>= 1; // 把最低位送到 CY(益处标志位) shift data to CY
if (--TBIT == 0) // 发送计数器减为0 表明单字节发送结束
{
TXB = 1; // 送停止位数据
TING = 0; // 发送停止位 stop send
TEND = 1; // 置位发送完成标志符 set send completed flag
}
else
{
TXB = CY; // 发送单b数据 write CY to TX port
}
}
}
}
}
#ifndef __UART_H
#include "config.h"
#include <stdio.h> // 如果内存不够,可以关闭这个头文件的包含,使用自定义的 uart_printf 函数输出字符串
#define BaudRate 9600 // 模拟串口波特率
#define Timer0_Reload (65536 - MAIN_Fosc / BaudRate / 3)
#define D_RxBitLenth 9 // 9: 8 + 1 stop
#define D_TxBitLenth 9 // 9: 1 stop bit
#define BUFF_SIZE 30 // 接受缓冲区大小
sbit RXB = P3^0; // define UART TX/RX port
sbit TXB = P3^1;
extern uchar data TBUF, RBUF;
extern uchar data TDAT, RDAT;
extern uchar data TCNT, RCNT; // 发送和接收检测 计数器(3倍速率检测)
extern uchar data TBIT, RBIT; // 发送和接收的数据计数器
extern uchar data t, r;
extern uchar data Rev_buf[BUFF_SIZE];
extern bit flag;
extern bit TING, RING; // 正在发送或接收一个字节
extern bit TEND, REND; // 发送或接收完成的标志位
#define RxBitLenth 9 // 8个数据位+1个停止位
#define TxBitLenth 9 // 8个数据位+1个停止位
void uart_init(void); // 串口初始化函数
void uart_send(uchar dat); // 发送一个字节函数
uchar uart_receive(void); // 接收函数
void uart_printf(uchar * p_buf); // 串口字符串打印
#endif /* __UART_H */