3198|4

7815

帖子

57

TA的资源

裸片初长成(中级)

楼主
 

【PSoC4】略有点小坑爹,Creator安装文件夹下的 温度传感器例程是有问题的 [复制链接]

安装路径下
C:\Program Files (x86)\Cypress\PSoC Creator\2.2\PSoC Creator\examples\sampleprojects

下面的 这个例程

ADC_SAR_Seq_DieTemp_PSoC4

我想看看那它的 SARADC中断服务函数都做了什么。先贴出代码。
  1. CY_ISR(ADC_SAR_SEQ_ISR_LOC)
  2. {
  3.     uint32 intr_status;
  4.     uint32 range_status;

  5.     /* Read interrupt status registers */
  6.     intr_status = ADC_SAR_SEQ_SAR_INTR_MASKED_REG;
  7.     /* Check for End of Scan interrupt */
  8.     if((intr_status & ADC_SAR_SEQ_EOS_MASK) != 0u)
  9.     {
  10.         /* Read range detect status */
  11.         range_status = ADC_SAR_SEQ_SAR_RANGE_INTR_MASKED_REG;
  12.         /* Verify that the conversion result met the condition Low_Limit <= Result < High_Limit  */
  13.         if((range_status & (uint32)(1ul << CH0_N)) != 0u)
  14.         {
  15.             /* Read conversion resoult */
  16.             result[CH0_N] = ADC_SAR_SEQ_GetResult16(CH0_N);
  17.             /* Set PWM compare from channel0 */
  18.             PWM_WriteCompare(result[CH0_N]);
  19.         }   
  20.         /* Clear range detect status */
  21.         ADC_SAR_SEQ_SAR_RANGE_INTR_REG = range_status;
  22.         dataReady |= ADC_SAR_SEQ_EOS_MASK;
  23.     }   
  24.     CY_ISR(ADC_SAR_SEQ_ISR_LOC)
  25. {
  26.     uint32 intr_status;
  27.     uint32 range_status;

  28.     /* Read interrupt status registers */
  29.     intr_status = ADC_SAR_SEQ_SAR_INTR_MASKED_REG;
  30.     /* Check for End of Scan interrupt */
  31.     if((intr_status & ADC_SAR_SEQ_EOS_MASK) != 0u)
  32.     {
  33.         /* Read range detect status */
  34.         range_status = ADC_SAR_SEQ_SAR_RANGE_INTR_MASKED_REG;
  35.         /* Verify that the conversion result met the condition Low_Limit <= Result < High_Limit  */
  36.         if((range_status & (uint32)(1ul << CH0_N)) != 0u)
  37.         {
  38.             /* Read conversion resoult */
  39.             result[CH0_N] = ADC_SAR_SEQ_GetResult16(CH0_N);
  40.             /* Set PWM compare from channel0 */
  41.             PWM_WriteCompare(result[CH0_N]);
  42.         }   
  43.         /* Clear range detect status */
  44.         ADC_SAR_SEQ_SAR_RANGE_INTR_REG = range_status;
  45.         dataReady |= ADC_SAR_SEQ_EOS_MASK;
  46.     }   
  47.     /* Check for Injection End of Conversion */
  48.     if((intr_status & ADC_SAR_SEQ_INJ_EOC_MASK) != 0u)
  49.     {
  50.         result[TEMP_CH] = ADC_SAR_SEQ_GetResult16(TEMP_CH);
  51.         dataReady |= ADC_SAR_SEQ_INJ_EOC_MASK;
  52.     }   

  53.     /* Clear handled interrupt */
  54.     ADC_SAR_SEQ_SAR_INTR_REG = intr_status;
  55. }

  56.     if((intr_status & ADC_SAR_SEQ_INJ_EOC_MASK) != 0u)
  57.     {
  58.         result[TEMP_CH] = ADC_SAR_SEQ_GetResult16(TEMP_CH);
  59.         dataReady |= ADC_SAR_SEQ_INJ_EOC_MASK;
  60.     }   

  61.     /* Clear handled interrupt */
  62.     ADC_SAR_SEQ_SAR_INTR_REG = intr_status;
  63. }
复制代码
这段代码写得挺乱的,就不说了。
可是我实际连上板子跑的时候,我发现,第二个if快
也就是
/* Check for Injection End of Conversion */
这一块始终没有进去。
我心里很奇怪,想找到问题所在,但因为不懂这个外设,花了不少时间看两份很长很长的Architect文档。
结果都是看得一塌糊涂。

心想你有例程,又有这样的驱动代码自动生成,怎么还能要我这么费劲呢?

但是这文档也不是白看的。
至少我知道了几个寄存器的含义。
然后今晚是看的第三个晚上,我心想再这么纠结不对。而且反正按照它代码的意思,它只是想 检查两个中断
一个是转换结束,一个是扫描结束。

今晚我再一次把昨晚看过的两份Architecture文档又仔细看了一遍相关的内容。
最后确定没什么特别的想法。

于是我用了最蠢的办法,我直接在程序里检查这些相关的 寄存器,主要是中断请求设置寄存器。

结果,我坑爹的发现,丫的,它根本就没设置 INJ_EOS_MASK.
那他能进得来才怪.....

于是我做了如下改动。

我在主函数里,三句调用之后,直接增加了 转换结束中断的位设置。
    ADC_SAR_SEQ_SAR_INTR_REG |= ADC_SAR_SEQ_INJ_EOC_MASK;
    ADC_SAR_SEQ_SAR_INTR_SET_REG |= ADC_SAR_SEQ_INJ_EOC_MASK;
在 使能CYPRESS全局中断以前
这样 main函数就成了
  1. void main()
  2. {
  3.     ADC_SAR_SEQ_Start();
  4.     ADC_SAR_SEQ_StartConvert();
  5.     ADC_SAR_SEQ_IRQ_StartEx(ADC_SAR_SEQ_ISR_LOC);
  6.    
  7.     ADC_SAR_SEQ_SAR_INTR_REG |= ADC_SAR_SEQ_INJ_EOC_MASK;
  8.     ADC_SAR_SEQ_SAR_INTR_SET_REG |= ADC_SAR_SEQ_INJ_EOC_MASK;

  9.     CyGlobalIntEnable;
  10.    
  11.     while(1);
  12. }
复制代码
这样再跑,我发现,丫的,终于进来了。
可是还是不对头。
我发现它进了一次就再也不会进来了。
为什么呢?

这个例程还是值得怀疑,这次我修改了一个我早就怀疑的地方。
    // clear interrupt handle;
    ADC_SAR_SEQ_SAR_INTR_REG &= ~ADC_SAR_SEQ_INJ_EOC_MASK ;

就是中断服务函数里的最后一句清除中断标志的语句

它原来的写法,你看到了,是这种莫名其妙很奇怪的写法
ADC_SAR_SEQ_SAR_INTR_REG = intr_status;

简直是莫名其妙。
此帖出自单片机论坛

最新回复

刚学硬件的萌新看的瑟瑟发抖 ADC_SAR_SEQ_SAR_INTR_REG = intr_status;这东西我根本连啥意思都不知道 好难好难,,,   详情 回复 发表于 2018-3-23 15:19
点赞 关注
 

回复
举报

7815

帖子

57

TA的资源

裸片初长成(中级)

沙发
 
在这个时候,我开始琢磨,为什么会出现没设置,刚开始我真担心是cypress这套自动生成驱动函数有问题。
但是转念一想,还是要确定一下,所以我首先细致检查了所有相关的函数的具体实现代码,发现没有出现我所担心的不用位操作的方式来设置寄存器

因为这些 中断标志位都是按照一个顺序出现在一系列不同含义的寄存器的相同位上,我直观担心它是因为没有用位操作,结果某些后面的设置覆盖了前面的标志。

但是看完代码,这个担心扫除了。

所以我只能认为问题出在。
这个例程本身写得乱七八糟。

这其实我从一开始就看出眉目。

比如这一句话就是做的莫名其妙的。
ADC_SAR_SEQ_SAR_INTR_REG = intr_status;

我当然知道他这样写的意图,他是认为,既然我已经进来了,那么就意味着,我肯定在这个位上有1,所以我写进去这个,就可以清除这个位。
这个地方,其实现在想起来我也不能说他是错的,但是我一改这个地方就正常了。

但这种写法本身是很不够严谨的。
你为什么不能明确清除哪一位呢?这样不是更清晰明了么?
其次,假如你真的起了好几个中断标志,而在这个中断服务函数里,你只是处理了其中两个,如果你这样处理,岂不是把其他可能的中断标志位也给清除了?
因为它是写1清0的寄存器模式。

其次就是,我发现它的好几个读写清除标志动作居然都不是用位操作,而是用直接赋值,这真是非常恐怖的错误。

所以得出的结论让我还挺安心
不是自动生成的代码有问题,是写例程的人乱来。
此帖出自单片机论坛
 
 

回复

7815

帖子

57

TA的资源

裸片初长成(中级)

板凳
 
至于结果本身,还有待接下去来折腾了。
顺带考虑一下怎么把这部分,是封装成函数加进去,还是找一找本来就有生成好的API直接引用,
此帖出自单片机论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

4
 
刚学硬件的萌新看的瑟瑟发抖
ADC_SAR_SEQ_SAR_INTR_REG = intr_status;这东西我根本连啥意思都不知道
好难好难,,,
此帖出自单片机论坛
 
 
 

回复

7815

帖子

57

TA的资源

裸片初长成(中级)

5
 
xufei616945741 发表于 2018-3-23 15:19
刚学硬件的萌新看的瑟瑟发抖
ADC_SAR_SEQ_SAR_INTR_REG = intr_status;这东西我根本连啥意思都不知道
:Cr ...

很久没弄了。
但显然
ADC_SAR_SEQ_SAR_INIT_REG应该是一个 寄存器(地址)
init_status就是一个变量啊,这就是给一个寄存器赋值,有什么不懂的。
此帖出自单片机论坛
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表