近期在做磁条刷卡器的驱动,需要通过两个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) |