【版 本】
1.0.0
【操作系统】
STC11L05E 单片机
【作 者】
谢红伟·chrys ·chrys@163.com ·http://callgle.xicp.net
【开发日期】
2009-07-15 10:11
【文档日期】
2009-07-18 17:14
【源代码下载】
无
用IAR编写的在芯片MSP430上能正常执行的代码放在用Keil C编写的执行在STC11L05E芯片上就会有奇怪的问题,这些代码在PC上执行也是正常的,看来STC11L05E芯片很不怎么滴啊!
1、在中断服务程序里收到一个字节的数据,调用一个函数,将该数据传递给函数,函数里将数据保存到一个全局的数组中,但保存进去的数据再次读出来的时候却被改变了,如果将这个函数的代码全部移到中断服务程序里却执行正常;
// 全局数组用来保存中断里收到的数据
unsigned char buf[32] = 0;
int nPos = 0;
void OnReceived ( unsigned char RecvData )
{
buf[nPos] = RecvData;
if ( buf[nPos] == RecvData ) // 错误:这里判断为FALSE
{
P1&=0xfe; // LED灯亮
}
nPos ++;
}
// 中断服务程序
void InterruptRoutine(void) interrupt 4 using 2
{
// static BOOL bFLag = FALSE;
if ( RI )
{
RI = 0;
OnReceived ( SBUF );
}
}
//---------------------------------------------------------
// 改成这样就没问题了
//---------------------------------------------------------
// 中断服务程序
void InterruptRoutine(void) interrupt 4 using 2
{
// static BOOL bFLag = FALSE;
if ( RI )
{
RI = 0;
buf[nPos] = SBUF;
if ( buf[nPos] == SBUF ) // 错误:这里判断为TRUE
{
P1&=0xfe; // LED灯亮
}
nPos ++;
}
}
2、Byte数据相乘前要强制转换为Short型,否则结果错。
unsigned char pData[4] = {0xaa, 0xbb, 0x17};
// 0x17 = (unsigned char)(0xaa * 0xbb / 2)
ASSERT ( pData[2] == (unsigned char)(pData[0]*pData[1]/2) ); // 断言失败
ASSERT ( pData[2] == (unsigned char)(((short)pData[0]*(short)pData[1])/2) ); // 断言成立,相乘前先转换为short型
3、将两个字节的Byte数赋值给一个Short变量时,最好采用移位的方法,直接操作指针会出错。
unsigned short nShort = 0;
unsigned char pCharArray[2] = {0x09, 0x00 };
// 期望nShort 变成0x0900,可Keil C执行完以后却是x0000
*((unsigned char*)&nShort) = *pCharArray;
*(((unsigned char*)&nShort)+1) = *(pCharArray+1);
// 改成移位的方式就没问题
nShort = pCharArray[0];
nShort |= ( ((unsigned short)pCharArray[1])<<8 );
总结:这些错误是我经过无数次地“修改代码->编译->烧录->通信测试->判断LED灯检查执行结果”反复操作而得到经验教训,这些问题的产生原因目前不得而知,请单片机编程工程师一起探讨并将您的看法回复本留言,谢谢!
编写单片机程序最好能用最精简的语法,否则编译器将会让你付出沉重的代价来排错,因为单片机的编译器是非常弱小的,按照杨森部长的话说“最后一绝招,那就是使用汇编”,可计算机技术日新月异,一日千里,汇编的时代理应早就过去了,汇编语言那是给机器去使用的语言,人类应该使用接近自然语言的编程方法,这样才能解决更复杂的业务逻辑。