偶刚刚接触STM32,发现了两个令人费解的问题,请香主及各位帮忙(使用Keil uVision3 V3.55A):
1、中断子程序的起始地址影响中断正常运行:
我将I2C2设成主机,并使用中断方式与I2C1通信,起初一切正常,这时I2C2中断程序的入口地址是0x08000A60,后来在主程序里增加了一些程序,发现I2C通信就不正常了,仔细查找后,发现这是由于I2C2程序的入口地址改变引起的,只要入口地址大于0x08000A64,程序就不正常了。
何解?是不是中断向量初始化不正确呢?
2、程序放置的地址不同,则运行时间不同?
由于需要精确控制脉冲频率及个数,我写了如下程序:
void PulseHigh(void)
{
GPIOB->ODR |= (1<<5); //H01
GPIOB->ODR |= (1<<5); //H02
GPIOB->ODR |= (1<<5); //H03
GPIOB->ODR |= (1<<5); //H04
GPIOB->ODR |= (1<<5); //H05
GPIOB->ODR |= (1<<5); //H06
GPIOB->ODR |= (1<<5); //H07
GPIOB->ODR |= (1<<5); //H08
GPIOB->ODR |= (1<<5); //H09
GPIOB->ODR |= (1<<5); //H10
GPIOB->ODR |= (1<<5); //H11
GPIOB->ODR |= (1<<5); //H12
GPIOB->ODR |= (1<<5); //H13
}
void PulseLow(void)
{
GPIOB->ODR &= ~(1<<5);//L01
GPIOB->ODR &= ~(1<<5);//L02
GPIOB->ODR &= ~(1<<5);//L03
GPIOB->ODR &= ~(1<<5);//L04
GPIOB->ODR &= ~(1<<5);//L05
GPIOB->ODR &= ~(1<<5);//L06
GPIOB->ODR &= ~(1<<5);//L07
GPIOB->ODR &= ~(1<<5);//L08
GPIOB->ODR &= ~(1<<5);//L09
GPIOB->ODR &= ~(1<<5);//L10
GPIOB->ODR &= ~(1<<5);//L11
GPIOB->ODR &= ~(1<<5);//L12
GPIOB->ODR &= ~(1<<5);//L13
}
调用过程如下:
PulseHigh();
PulseLow();
PulseHigh();
PulseLow();
……
但奇怪的事情发生了,此时占空比不为1:1,高的时间为1.98us,低的时间为1.94us,但把PulseHigh, PulseLow两个子程序摆放顺序(注意不是调用顺序)对调一下,占空比也跟着对调了,高的时间变成1.94us,低的时间为1.98us。百思不得其解!特求助香主及各位!
那个I2C就不值得一提了。
LZ这个测试时间,使用SZ示波器看的吧? 这么精确?
还有,你最好用位带操作,并把仿真是汇编看看,或把编译的汇编输出LST文件看看再说吧!
为什么不值得一提?
为什么不值得一提?
我刚刚又发现示波器探头加在SDA上,通信正常,拿开,通信有不正常了,起始条件后马上就是停止。
有加精的I2C程序,中断方式的啊!LZ可以找找。
应该都是LZ的程序问题。程序不稳定,也先不要急。或者你的KEL有问题呢!
这么时髦的KEIL会不会有BUG?
SZ示波器
谢谢netjob,
SZ示波器 = 山寨示波器?
No,我用的是 安捷伦DSO6034A 2G采样率 300MHz带宽。
STM32的闪存存储器接口上有一个预取缓冲区
这个预取缓冲区的作用是减小较慢的闪存对CPU取指速度的影响。
楼主的第二个问题中子程序对调存放位置后,时序产生变化可能有2个原因:
1)闪存预取缓冲区的长度为8字节,子程序的起始地址没有与8字节对齐时,可能造成进入子程序时,在预取缓冲区上多等了1~2个周期。
2)因为调用这2个子程序(函数)的指令至子程序入口地址的距离不同,造成调用距离较短的那个函数的指令与调用距离较远的那个函数的指令,不是同样的指令,比如一个是相对跳转而另一个是绝对跳转。
检查是否为这2种可能,需要察看程序的汇编指令和地址分配情况。
怀疑楼主的第一个问题也与上述2种情况有关。
搞定
I2C的问题搞定,似乎跟中断优先级的设置有关。
GPIO的问题搞不清,换了一种写法,改用异或,也算搞定。
感觉STM32里面水还不浅,得慢慢琢磨。。。。。。