使用定时器中断实现18b20的读取

现在mcu性能越来越好了,但是在网上看到的读取18b20传感器数据的代码都是通过阻塞延时方式做通信时序实现的,跑os也只能提供毫秒级的延时释放cpu资源,做不到18b20需要的微秒级通信时序,于是想着通过定时器中断的方式实现,读取数据时其它任务不会阻塞,废话不多说,直接贴代码。测试环境stm32f407主频168M,使用HAL库。


typedef enum{
	DS_IDEL=0,  	//无操作
	DS_RESET,		//复位
	DS_READ,		//读
	DS_WRITE,		//写
}DS18STATUS;

typedef enum{
	USER_DLY1 = 0,
	USER_RESET1,
	USER_W_CC1,
	USER_W_44,
	USER_DLY2,
	USER_RESET2,
	USER_W_CC2,
	USER_W_BE,
	USER_R_L,
	USER_R_H,
}DS18STEP;

void ds18b20_irq_fun( void );



#define DS18B20_IO_MODE(x) DS18B20_DQ_init(x) 

//IO操作函数											   
#define DS18B20_DQ_OUT(x)   do{ x ? \
                                HAL_GPIO_WritePin(IO_Ctr[temp_num], IO_Port[temp_num], GPIO_PIN_SET) : \
                                HAL_GPIO_WritePin(IO_Ctr[temp_num], IO_Port[temp_num], GPIO_PIN_RESET); \
                            }while(0)    

#define	DS18B20_DQ_IN  HAL_GPIO_ReadPin(IO_Ctr[temp_num], IO_Port[temp_num])

uint8_t temp_num = 0;
static GPIO_TypeDef * IO_Ctr[2] = {TEMP1_GPIO_Port,TEMP2_GPIO_Port};
static uint16_t IO_Port[2] = {TEMP1_Pin,TEMP2_Pin};

float temp_t[2] = {0};


//定时器方式重新实现驱动(初始化5us中断调用)
void ds18b20_irq_fun( void )
{
	static uint8_t step_t = 0;
	static uint8_t status_t = 0;
	static uint8_t run_status_t = 0;
	static uint32_t this_dly_t = 0;
	static uint8_t write_data = 0;
	static uint8_t write_num = 0;
	static uint8_t read_data = 0;
	static uint8_t read_num = 0;
	static int16_t read_temp = 0;
	static uint8_t init_dly = 2;
	
	MYCON:
	if(status_t==DS_IDEL){
		switch(step_t){
			case USER_DLY1:{
				if(this_dly_t<100){//每次采集间隔10ms*100=1s
					this_dly_t++;
				}else{
					__HAL_TIM_SET_AUTORELOAD(&htim4,5-1);//5us
					this_dly_t=0;
					step_t = USER_RESET1;
					status_t = DS_RESET;
				}
			}break;
			case USER_RESET1:{
				if( status_t==DS_IDEL ){
					step_t = USER_W_CC1;
					status_t = DS_WRITE;
					write_data = 0xcc;
					write_num = 0;
				}
			}break;
			case USER_W_CC1:{
				if( status_t==DS_IDEL ){
					step_t = USER_W_44;
					status_t = DS_WRITE;
					write_data = 0x44;
					write_num = 0;
				}
			}break;
			case USER_W_44:{
				if( status_t==DS_IDEL ){
					step_t = USER_DLY2;
				}else{
					break;
				}
			}
			case USER_DLY2:{
				if(this_dly_t<151999){
					this_dly_t++;
				}else
				{
					this_dly_t=0;
					step_t = USER_RESET2;
					status_t = DS_RESET;
					if(init_dly>0){
						init_dly--;
					}
				}
				if(init_dly>0){
					break;
				}else{
					step_t = USER_RESET2;
					status_t = DS_RESET;
				}
			}
			case USER_RESET2:{
				if( status_t==DS_IDEL ){
					step_t = USER_W_CC2;
					status_t = DS_WRITE;
					write_data = 0xCC;
					write_num = 0;
				}
			}break;
			case USER_W_CC2:{
				if( status_t==DS_IDEL ){
					step_t = USER_W_BE;
					status_t = DS_WRITE;
					write_data = 0xBE;
					write_num = 0;
				}
			}break;
			case USER_W_BE:{
				if( status_t==DS_IDEL ){
					step_t = USER_R_L;
					status_t = DS_READ;
					read_num = 0;
					read_data = 0;
				}
			}break;
			case USER_R_L:{
				if( status_t==DS_IDEL ){
					read_temp = read_data;
					step_t = USER_R_H;
					status_t = DS_READ;
					read_num = 0;
					read_data = 0;
				}
			}break;
			case USER_R_H:{
				if( status_t==DS_IDEL ){
					read_temp |= (uint16_t)read_data<<8;
					//这里只转存数据,中断中不执行发送显示等操作
					if(read_temp<0){
						temp_t[0] = (~read_temp+1)*0.0625;
					}else{
						temp_t[0] = read_temp*0.0625;
					}
					step_t = USER_DLY1;
					__HAL_TIM_SET_AUTORELOAD(&htim4,10000-1);//10ms
				}
			}break;
		}	
	}
	
	if(status_t!=DS_IDEL){
		MYREAD:
		switch(status_t){
			case DS_IDEL:{
			}break;
			case DS_RESET:{
				switch(run_status_t){
					case 0:{
						DS18B20_IO_MODE(1);
						DS18B20_DQ_OUT(1);
						run_status_t++;
					}break;
					case 1:{
						if(this_dly_t<1){
							this_dly_t++;
						}else{
							this_dly_t=0;
							DS18B20_DQ_OUT(0);
							run_status_t++;
						}
					}break;
					case 2:{
						if(this_dly_t<143){
							this_dly_t++;
						}else{
							this_dly_t=0;
							DS18B20_IO_MODE(0);
							run_status_t++;
						}
					}break;
					case 3:{
						if(this_dly_t<213){
							this_dly_t++;
						}else{
							this_dly_t=0;
							status_t = DS_IDEL;
							run_status_t=0;
						}
					}break;
				}
			}break;
			case DS_READ:{
				switch(run_status_t){
					case 0:{
						DS18B20_DQ_OUT(1);
						DS18B20_IO_MODE(1);
						run_status_t++;
					}
					break;
					case 1:{
						if(this_dly_t<1){
							this_dly_t++;
						}else{
							this_dly_t=0;
							DS18B20_DQ_OUT(0);
							run_status_t++;
						}
					}break;
					case 2:{
						DS18B20_IO_MODE(0);
						run_status_t++;
					}break;
					case 3:{
						read_data |= ((uint8_t)DS18B20_DQ_IN<<read_num);
						read_num++;
						run_status_t++;
					}break;
					case 4:{
						if(this_dly_t<11){
							this_dly_t++;
						}else{
							this_dly_t=0;
							if(read_num==8){
								status_t = DS_IDEL;
								run_status_t=0;
								goto MYCON;
							}else{
								run_status_t=0;
								goto MYREAD;
							}
						}
					}break;
				}
			}break;
			case DS_WRITE:{
				switch(run_status_t){
					case 0:{
							DS18B20_IO_MODE(1);
							DS18B20_DQ_OUT(1);
							run_status_t++;
					}break;
					case 1:{
						if(this_dly_t<1){
							this_dly_t++;
						}else{
							this_dly_t=0;
							DS18B20_DQ_OUT(0);
							run_status_t++;
						}
					}break;
					case 2:{
						if(this_dly_t<1){
							this_dly_t++;
						}else{
							this_dly_t=0;
							DS18B20_DQ_OUT((write_data>>write_num)&0x01);
							run_status_t++;
						}
					}break;
					case 3:{
						if(this_dly_t<11){
							this_dly_t++;
						}else{
							this_dly_t=0;
							DS18B20_IO_MODE(0);
							write_num++;
							if(write_num==8){
								run_status_t++;
							}else{
								run_status_t = 0;
							}
						}
					}break;
					case 4:{
						if(this_dly_t<7){
							this_dly_t++;
						}else{
							this_dly_t=0;
							status_t = DS_IDEL;
							run_status_t=0;
						}
					}break;
				}
			}break;
		}	
	}
	
}


  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值