今天又犯了老错误。新板子用原来的老程序,需要修改一些管脚定义,由于开头的管脚的宏定义没有用好,导致函数中有个地方有句跟硬件相关的代码没有修改,调试了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;
}
这样,再做移植的话只需要将宏定义部分仔细修改一下即可,代码部分就不用操心了。参考别人的代码的时候,一定记着只是参考,要批判性地用。
文章评论(0条评论)
登录后参与讨论