现在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;
}
}
}