Chinaunix首页 | 论坛 | 博客
  • 博客访问: 106544
  • 博文数量: 26
  • 博客积分: 1060
  • 博客等级: 少尉
  • 技术积分: 300
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-04 10:32
文章分类

全部博文(26)

文章存档

2013年(1)

2011年(21)

2010年(4)

分类: 嵌入式

2011-04-18 12:11:05

近期在做磁条刷卡器的驱动,需要通过两个IO口输出高低电平序列将磁条刷卡器开机初始化为新模式。
我按照Datasheet 写好后,怎么调试都无法进入新模式。给厂家打电话也无法解决。最总决定重写所有代码,很凑巧的搞定了。对比错误代码,和正确代码:

运行良好的代码1:

VOID IO_set_StrobeHigh()
{
    v_pIOPregs->GPPCON = (v_pIOPregs->GPPCON & (~(0x3 << 16))) | (0x1 << 16);
    v_pIOPregs->GPPDAT |= 0x01 << 8;
}
VOID IO_set_StrobeLow()
{
    v_pIOPregs->GPPCON = (v_pIOPregs->GPPCON & (~(0x3 << 16))) | (0x1 << 16);
    v_pIOPregs->GPPDAT &= ~(0x01 << 8);
}


无法得到结果的代码2:

VOID IO_set_StrobeHigh()
{
    v_pIOPregs->GPPCON &= (~(0x03 << 16));
    v_pIOPregs->GPPCON |= 0x01 << 16;
    v_pIOPregs->GPPDAT |= 0x01 << 8;
}

VOID IO_set_StrobeLow()
{
    v_pIOPregs->GPPCON &= (~(0x03 << 16));
    v_pIOPregs->GPPCON |= 0x01 << 16;
    v_pIOPregs->GPPDAT &= ~(0x01 << 8);
}


事后比较两处代码,在示波器上看到得波形完全一样。但是结果确不一样。

后来询问高手,意见不一,大致如下:

总结一下大家的回答:
1. 编译器问题:
  1.1 编译器将代码2作为8位来处理得。
  针对这个,我将代码修改为:
C/C++ code
VOID IO_set_strobe_H()
{
    v_pIOPregs->GPPCON &=  (~(0x00000003 << 16));
    v_pIOPregs->GPPCON |= 0x00000001 << 16;
    v_pIOPregs->GPPDAT |= 0x00000001 << 8;
}
VOID IO_set_strobe_L()
{
    v_pIOPregs->GPPCON &=  (~(0x00000003 << 16));
    v_pIOPregs->GPPCON |= 0x00000001 << 16;
    v_pIOPregs->GPPDAT &= ~(0x00000001 << 8);
}



重新测试,问题依旧。
1.2 编译器优化问题。
  这个我对vs2005 编译器不太熟悉。没有论证。

2. 寄存器配置问题
  这种说法主要是说代码2分两步设置IO为输出状态:
  第一步是现将IO口配置为输入状态,
  然后再配置为输出状态。
  这个时候第一步设为输入状态会产生隐患,输入状态下,IO口电平可能会被外部电路拉高或者拉低,产生毛刺。 如果在这一步被中断,毛刺可能会更大。



至于示波器问题, 我写得延时函数是us 级的,但S3C6410命令执行是ns 级的, 示波器没有分析出毛刺成分也是可能的。


总的来说,我比较倾向于第二种说法,将寄存器配置成输入状态会造成隐患。

这些都是写驱动中得经验问题,自己经验还是太少。
谢谢大家的热心回复。

阅读(1492) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~