• TSIC506驱动程序


    测试使用的MCU 型号

    • STC15F104W
    • 内部架构
      在这里插入图片描述

    传感器型简介

    在这里插入图片描述

    传感器原理图

    在这里插入图片描述

    TSIC506 主驱动代码

    • config.h 文件:主要配置系统时钟主频
    // ------------------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
                    }
                }
            }
        }
    }
    
    • uart头文件uart.h
    #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 */
    
    
  • 相关阅读:
    [CSP-S模拟测试]:party?(霍尔定理+最小割+树链剖分)
    [CSP-S模拟测试]:marshland(最大费用可行流)
    [CSP-S模拟测试]:Revive(点分治)
    [CSP-S模拟测试]:Lighthouse(哈密顿回路+容斥)
    [CSP-S模拟测试]:Lost My Music(凸包)
    [CSP-S模拟测试]:God Knows(线段树维护单调栈)
    [CSP-S模拟测试]:Star Way To Heaven(最小生成树Prim)
    [CSP-S模拟测试]:gcd(莫比乌斯反演)
    [CSP-S模拟测试]:water(BFS)
    BZOJ3462 DZY Loves Math II 【多重背包 + 组合数】
  • 原文地址:https://www.cnblogs.com/veis/p/12486391.html
Copyright © 2020-2023  润新知