本帖最后由 芯圣电子官方QQ 于 2023-7-25 13:53 编辑
这几天在用HC89S105K8移植原来STM8S003的产品。陆续遇到一些问题。也一一解决。过程中耽误了时间,来来回回检查试验。显然这并不是什么高深的问题。而往往耽误时间的就是一些没有被注意到的细节。在PCA的调试过程中,也是因为没有注意细节。耽误了不少时间。今天总算顺利完成。忍不住发贴分享一下。
HC89S105官网PCA例程是这样的
void main(void)
{
/********************************系统初始化*******************************************/
WDTCCR = 0x00; //关闭看门狗
//本例程为方便测试关闭看门狗,实际使用中,建议客户打开看门狗,详见WDT复位例程
CLKCON = 0x02; //打开内部高速RC
CLKDIV = 0x02; //CPU时钟2分频,确保在进行RC32分频时CPU时钟小于16M
/**********************************相关配置初始化**************************************/
P0M0 = P0M0&0xF0|0x02; //P00设置为上拉输入
P0M0 = P0M0&0x0F|0x80; //P01设置为推挽输出
/**********************************PCA配置初始化**************************************/
PCA0_MAP = 0x00; //捕获输入口映射P00
PCAMOD0 = 0x20; //16位捕获模式,上升沿触发
CCAPL0 = 0x00;
CCAPH0 = 0x00;
PCACLK = 0x0F; //系统时钟8分频,允许寄存器PCACON中CF位的中断
PCACON = 0x40; //开PCA计数器
EA = 1; //使能总中断
while(1);
}
void PCA_Rpt() interrupt PCA_VECTOR
{
PCAValue = CCAP0; //获取当前数据
CCAPL0 = 0x00;
CCAPH0 = 0x00;
P0_1 =~P0_1; //P01翻转
PCACON &=~ 0x01; //清除中断标志位
}
我参考这个PCA例程移植原STM8S003项目的代码(一个捕获方波脉冲信号的代码)
void pca_init(void)
{
PCA0_MAP = 0x1b;
PCAMOD0 = 0x21; //16位捕获模式,上升沿触发
CCAP0 = 0x00;
PCAC=0;
PCACLK = 0x0F; //系统时钟8分频,允许寄存器PCACON中CF位的中断
PCACON = 0x40; //开PCA计数器
}
void PCA_Rpt() interrupt PCA_VECTOR
{
if(PCACON&0x80) //发生超时
{
//超时处理代码
}
else if(PCACON&0x01)
{
if(PCAMOD0&0x10)//下降沿
{
high=CCAP0*2; //乘2得到1us
PCAMOD0 = 0x21;//16位捕获模式,上升沿触发
}
else//上升沿
{
low=CCAP0*2; //乘2得到1us
PCAMOD0 = 0x11;//16位捕获模式,下降沿触发
}
}
CCAP0=0;
PCACON&=~0x01;
}
用不了,然后网上搜索,发现HC89S105的资料实在太缺乏了。PCA的贴子更是只有一个。看到了这个贴子帮助还是十分大的。感谢!
https://bbs.21ic.com/icview-2935046-1-1.html
然后将PCACON&=~0x01;改成了PCACON&=~0x81;清除一下计数溢出标志位(超时溢出了也没测到有效的方波信号,这数据肯定是无效的)。
然后,还是不能用,捕获测出来的电平宽度总是不对的。或大或小没有规律。看起来像是干扰信号似的。接连几天,我一直在怀疑质疑中度过。经常以为是不是引脚映射没对?端口相关寄存器不对?硬件是不是有问题?然后又拆了HC89S105K8换回STM8S003,证实硬件是没有问题的。反复参考官网例程都是没有问题的。例程也是这样赋值的。实在没办法了,回头看STM8的程序,一步一步对比。发现STM8的多一步计数器清零的动作。
于是乎程序改成这样就一切正常了。
void PCA_Rpt() interrupt PCA_VECTOR
{
if(PCACON&0x80) //发生超时
{
//超时处理代码
}
else if(PCACON&0x01)
{
if(PCAMOD0&0x10)//下降沿
{
high=CCAP0*2; //乘2得到1us
PCAMOD0 = 0x21;//16位捕获模式,上升沿触发
}
else//上升沿
{
low=CCAP0*2; //乘2得到1us
PCAMOD0 = 0x11;//16位捕获模式,下降沿触发
}
}
CCAP0=0;
PCAC=0;
PCACON&=~0x81;
}
PCAC=0;计数器清零。重新开始计数才能得到正确的值。
官网例程的确能进入中断,然而得不到正确的值。因为计数器没清零。
感觉这官网例程有点精糙。
还是怪自己没注意细节。
|