当前位置:首页 > 嵌入式 > 嵌入式大杂烩
[导读]关注「嵌入式大杂烩」,选择「星标公众号」一起进步!作者 |  Acuity1.前言onewire(单总线)是DALLAS公司推出的外围串行扩展总线技术总线,顾名思义,它是采用一根信号线进行通信,既传输时钟信号又传输数据,而且能够进行双向通信,具有节省I/O口线、资源结构简单、成本...

关注「嵌入式大杂烩」,选择「星标公众号」一起进步!

作者 |  Acuity

1.前言

onewire(单总线) 是DALLAS公司推出的外围串行扩展总线技术总线,顾名思义,它是采用一根信号线进行通信,既传输时钟信号又传输数据,而且能够进行双向通信,具有节省I/O口线、资源结构简单、成本低廉、便于总线扩展和维护等诸多优点。

常用到单总线的器件,一般是温度传感器、EEPROM、唯一序列号芯片等,如DS18B20、DS2431。

在使用单总线时,往往很少CPU会提供硬件单总线,几乎都是根据单总线标准的时序图,通过普通IO翻转模拟实现单总线。而在模式实现时序图的过程中,需要根据CPU时钟频率等条件进行时序时间计算,如果更换CPU后,需要重新计算时序时间,如果时序代码和器件外设控制代码集成在一起,则代码改动比较大。

或者同一CPU需要模拟多根单总线时,传统的“复制”方式使得程序显得累赘,还增加ROM占用空间。因此,可以利用“函数指针”的方式,将时序部分抽象出来,达到“复用”代码的效果,减少重复代码编写。

2.onewire 抽象

2.1 onewire 结构体

onewire结构体主要是对与CPU底层相关的操作抽象分离,调用时只需将该结构体地址(指针)作为函数入口参数,通过该指针实现对底层函数的回调。该结构体我们命名为“struct ops_onewire_dev”,其原型如下:

struct ops_onewire_dev
{

  void (*set_sdo)(int8_t state);
    uint8_t (*get_sdo)(void);
    void (*delayus)(uint32_t us);
};
其中: 

1)set_sdo:IO输出1bit,包括时钟和数据。 

2)get_sdo:IO输入1bit,包括时钟和数据。

3)delayus:时序延时函数,根据CPU频率进行计算。

回调函数相关文章:C语言、嵌入式重点知识:回调函数

2.2 onewire 对外接口

extern uint8_t ops_onewire_reset(struct ops_onewire_dev *onewire);
extern int ops_onewire_read(struct ops_onewire_dev *onewire,void *buff,int size);
extern int ops_onewire_write(struct ops_onewire_dev *onewire,void *buff,int size);
1)分别为复位函数、读函数、写函数。 

2)入口首参数为“struct ops_onewire_dev”结构体指针,此部分就是硬件层相关,需要后期初始化的. 

3)其余入口参数易于理解,读/写缓存及数据大小。

2.3 onewire 抽象接口实现

分别实现上述三者函数接口。

2.3.1 复位函数

复位函数,在单总线初始化外设器件时需要用到,用于判断总线与器件是否通信上,类似“握手”的动作。如图,为DS18B20的复位时序图,以下与单总线相关的时序图,都是以DS18B20为例,因为此芯片为单总线应用的经典。

根据时序图,实现复位函数。

/**
  * @brief  单总线复位时序
  * @param  onewire 总线结构体指针
  * @retval 成功返回0
*/

uint8_t ops_onewire_reset(struct ops_onewire_dev *onewire)
{
 uint8_t ret = 0;
 
 onewire->set_sdo(1);
 onewire->delayus(50);
 onewire->set_sdo(0);
 onewire->delayus(500);
 onewire->set_sdo(1);
 onewire->delayus(40);
 ret = onewire->get_sdo();
 onewire->delayus(500);
 onewire->set_sdo(1);
 return ret;
}

2.3.2 读函数

读函数即以该函数,通过单总线从外设上读取数据,至于代码的实现,完全是时序图的实现,无特殊难点。先实现单字节读函数,再通过调用单字节读函数实现多字节读函数。

/**
  * @brief  单总线读取一字节数据
  * @param  onewire 总线结构体指针
  * @retval 返回读取的数据
*/

static char ops_onewire_read_byte(struct ops_onewire_dev *onewire)
{
 char data = 0;
 uint8_t i;
 
 for(i=8;i>0;i--)
 {
  data >>= 1;
  onewire->set_sdo(0);
  onewire->delayus(5);
  onewire->set_sdo(1);
  onewire->delayus(5);
  if(onewire->get_sdo())
   data |= 0x80;
  else
   data 
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
换一批
延伸阅读
关闭