原创 使用宏定义方便硬件相关的代码移植

2008-11-4 16:03 3501 11 11 分类: MCU/ 嵌入式

    今天又犯了老错误。新板子用原来的老程序,需要修改一些管脚定义,由于开头的管脚的宏定义没有用好,导致函数中有个地方有句跟硬件相关的代码没有修改,调试了1天才发现问题。


    下面就详细介绍一下这个问题。想想问题在哪里,如何来避免这个问题。


     最初的程序是借鉴了别人的代码,有点盲目崇拜,直接拿来用,也没有去怀疑代码是否是最好的。具体的代码如下:


#define noACK 0
#define ACK 1


#define STATUS_REG_W  0x06
#define STATUS_REG_R  0x07
#define MEASURE_TEMP  0x03
#define MEASURE_HUMI  0x05
#define RESET         0x1e



#define setREAD       DDRB |=(1<<PB3); PORTB|=(1<<PB3);DDRB &= ~(1<<PB4)
#define setWRITE      DDRB |=(1<<PB3); DDRB |=(1<<PB4)//outb(DDRB, 0x03)
#define SCK(i)        if (i) PORTB|=(1<<PB3); else PORTB &= ~(1<<PB3)
#define DATA(i)       if (i) PORTB|=(1<<PB4); else PORTB &= ~(1<<PB4)


//  enum {TEMP, HUMI};



void delay_us(unsigned int us) {
  while (us) us--;
}



void delay_ms(unsigned int ms) {
  unsigned int outer1, outer2;
  outer1 = 2000;
  while (outer1) {
    outer2 = 10000;
    while (outer2) {
      while ( ms ) ms--;
      outer2--;
    }
    outer1--;
  }
}



void TransStart(void)
{
  DATA(1);//数据位置1 
  SCK(0);//sck清0
  delay_us(1);//延时
  SCK(1);//sck置1
  delay_us(1);//延时
  DATA(0);//数据变低
  delay_us(1);//延时
  SCK(0);//sck降低
  delay_us(5);//延时
  SCK(1);//sck置高
  delay_us(1);//延时
  DATA(1);//数据置高
  delay_us(1);//延时
  SCK(0);//sck清0
}



void ConnReset(void)
{
  unsigned int i;
  setWRITE;
  DATA(1); SCK(0);
  for(i=0; i<9; i++) {
    SCK(1);
    SCK(0);
  }
  TransStart();//发送开始信号
}



unsigned int GetDATA()
{
  return bit_is_set(PINB, PB4);
}



unsigned char WriteByte(unsigned char value) {
  unsigned char i, error="0";
  setWRITE;                  //设置为写
  for(i=0x80;i>0;i/=2)
  {
    if (i & value) DATA(1);//先输出最高位
    else DATA(0);
    SCK(1);                 //产生一个下降沿
    delay_us(5);
    SCK(0);
  }
  setREAD;                  //设置为读
  SCK(1);                   //SCK设置为高
  delay_us(1);              //延时
  error="GetDATA"();          //获取ACK数据
  SCK(0);                  
  return error;
}



unsigned char ReadByte(unsigned char ack) {
  unsigned char i,val=0;
  setREAD;                 //设置为读
  for(i=0x80;i>0;i/=2)
  {
    SCK(1);                //置高
    if (GetDATA()) val=(val | i);  //获取数据
    SCK(0);                        //拉低
  }
  setWRITE;                        //设置为写
  DATA(!ack);
  SCK(1);
  delay_us(5);
  SCK(0);
  return val;
}



unsigned char measure(unsigned int *p_value, unsigned char *p_checksum, unsigned char mode) {
  unsigned char lsb,msb,check;
  unsigned char error="0";
  unsigned int i;


  TransStart();//开始传输
  switch(mode) //发送温度或者湿度
  {
    case TEMP : error+=WriteByte(MEASURE_TEMP); break;
    case HUMI : error+=WriteByte(MEASURE_HUMI); break;
    default   : break;
  }
  setREAD;     //设置为读
  for(i=0;i<65535;i++) if (GetDATA()==0) break;//等待DATA电平变高
  if (GetDATA()) error+=1;  //如果变高,加1
  *p_value = ReadByte(ACK); //读字节
  *p_value<<=8;
  *p_value+= ReadByte(ACK);//再读一个字节
  *p_checksum = ReadByte(noACK);//读CRC
  return error;


    上面的代码跟硬件相关的地方有2个。一个是最初的宏定义部分。第二部分是上面红色的函数中,读取管脚状态的函数也跟硬件相关。我应用的时候,只注意到上面宏定义中跟硬件相关代码的修改,而没有注意到函数内部跟硬件相关的代码,结果半天没有调试通过。


    重新写了这部分代码,将与硬件相关的代码用宏定义的方式放在文件的开头。


 /* ----------------------- Defines ------------------------------------------*/
#define noACK 0
#define ACK 1


#define STATUS_REG_W  0x06
#define STATUS_REG_R  0x07
#define MEASURE_TEMP  0x03
#define MEASURE_HUMI  0x05
#define RESET         0x1e


//SCK--PB1 DATA--PB0
#define SCK_PORT      PORTB
#define SCK_PIN       PB1
#define SCK_DDR       DDRB


#define DATA_PORT     PORTB
#define DATA_PIN      PB0
#define DATA_DDR      DDRB


#define GET_DATA_PORT  PINB
#define GET_DATA_PIN   PB0


#define setREAD       SCK_DDR |= (1<<SCK_PIN); DATA_PORT|=(1<<DATA_PIN);DATA_DDR &= ~(1<<DATA_PIN)
#define setWRITE      SCK_DDR |= (1<<SCK_PIN);                         DATA_DDR |=(1<<DATA_PIN)
#define SCK(i)        if (i) SCK_PORT|=(1<<SCK_PIN); else SCK_PORT &= ~(1<<SCK_PIN)
#define DATA(i)       if (i) DATA_PORT|=(1<<DATA_PIN); else DATA_PORT &= ~(1<<DATA_PIN)


 


//  enum {TEMP, HUMI};


void delay_us(unsigned int us)
{
  while (us)
  {
     _delay_us(10);
     us--;
   }
}



void delay_ms(unsigned int ms)
{
  unsigned int outer1, outer2;
  outer1 = 2000;
  while (outer1) {
    outer2 = 10000;
    while (outer2) {
      while ( ms ) ms--;
      outer2--;
    }
    outer1--;
  }
}



void TransStart(void)
{
  DATA(1);//数据位置1 
  SCK(0);//sck清0
  delay_us(1);//延时
  SCK(1);//sck置1
  delay_us(1);//延时
  DATA(0);//数据变低
  delay_us(1);//延时
  SCK(0);//sck降低
  delay_us(5);//延时
  SCK(1);//sck置高
  delay_us(1);//延时
  DATA(1);//数据置高
  delay_us(1);//延时
  SCK(0);//sck清0
  delay_us(1);//延时
}



void ConnReset(void)
{
  unsigned int i;
  setWRITE;
  delay_us(1);//延时
  DATA(1); SCK(0);
  for(i=0; i<9; i++) {
    SCK(1);
 delay_us(1);//延时
    SCK(0);
 delay_us(1);//延时
  }
  delay_us(1);//延时
  TransStart();//发送开始信号
}



unsigned int GetDATA()
{
  return bit_is_set(GET_DATA_PORT, DATA_PIN);
}



unsigned char WriteByte(unsigned char value)
{
  unsigned char i, error="0";
  setWRITE; 
  delay_us(1);//延时                //设置为写
  for(i=0x80;i>0;i/=2)
  {
    if (i & value) DATA(1);//先输出最高位
    else DATA(0);
 delay_us(1);//延时
    SCK(1);                 //产生一个下降沿
    delay_us(5);
    SCK(0);
 delay_us(1);//延时
  }
  delay_us(1);//延时
  setREAD;                  //设置为读
  delay_us(1);//延时
  SCK(1);                   //SCK设置为高
  delay_us(1);              //延时
  error="GetDATA"();          //获取SCK数据
  SCK(0); 
  delay_us(1);//延时                
  return error;
}



unsigned char ReadByte(unsigned char ack)
{
  unsigned char i,val=0;
  setREAD;                 //设置为读
  delay_us(1);//延时
  for(i=0x80;i>0;i/=2)
  {
    SCK(1);                //置高
 delay_us(1);//延时
    if (GetDATA()) val=(val | i);  //获取数据
    SCK(0);                        //拉低
 delay_us(1);//延时
  }
  delay_us(1);//延时
  setWRITE;                        //设置为写
  delay_us(1);//延时
  DATA(!ack);
  delay_us(1);//延时
  SCK(1);
  delay_us(5);
  SCK(0);
  delay_us(1);//延时
  return val;
}



unsigned char measure(USHORT *p_value, unsigned char *p_checksum, unsigned char mode)
{
  //unsigned char lsb,msb;
  unsigned char error="0";
  unsigned int i;
  TransStart();//开始传输
  switch(mode) //发送温度或者湿度
  {
    case TEMP : error+=WriteByte(MEASURE_TEMP); break;
    case HUMI : error+=WriteByte(MEASURE_HUMI); break;
    default   : break;
  }
  setREAD;     //设置为读



  for(i=0;i<655;i++)
  {
   _delay_ms(1);
    if (GetDATA()==0)
    break;//等待DATA电平变高
  }
  if (GetDATA())
  {
      error+=1;  //如果变高,加1
   }


 *p_value = ReadByte(ACK); //读字节
  *p_value<<=8;
  *p_value+= ReadByte(ACK);//再读一个字节

  *p_checksum = ReadByte(noACK);//读CRC
  return error;


    这样,再做移植的话只需要将宏定义部分仔细修改一下即可,代码部分就不用操心了。参考别人的代码的时候,一定记着只是参考,要批判性地用。


 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
11
关闭 站长推荐上一条 /3 下一条