【PSoC4】略有点小坑爹,Creator安装文件夹下的 温度传感器例程是有问题的
[复制链接]
安装路径下
C:\Program Files (x86)\Cypress\PSoC Creator\2.2\PSoC Creator\examples\sampleprojects
下面的 这个例程
ADC_SAR_Seq_DieTemp_PSoC4
我想看看那它的 SARADC中断服务函数都做了什么。先贴出代码。CY_ISR(ADC_SAR_SEQ_ISR_LOC)
{
uint32 intr_status;
uint32 range_status;
/* Read interrupt status registers */
intr_status = ADC_SAR_SEQ_SAR_INTR_MASKED_REG;
/* Check for End of Scan interrupt */
if((intr_status & ADC_SAR_SEQ_EOS_MASK) != 0u)
{
/* Read range detect status */
range_status = ADC_SAR_SEQ_SAR_RANGE_INTR_MASKED_REG;
/* Verify that the conversion result met the condition Low_Limit <= Result < High_Limit */
if((range_status & (uint32)(1ul << CH0_N)) != 0u)
{
/* Read conversion resoult */
result[CH0_N] = ADC_SAR_SEQ_GetResult16(CH0_N);
/* Set PWM compare from channel0 */
PWM_WriteCompare(result[CH0_N]);
}
/* Clear range detect status */
ADC_SAR_SEQ_SAR_RANGE_INTR_REG = range_status;
dataReady |= ADC_SAR_SEQ_EOS_MASK;
}
CY_ISR(ADC_SAR_SEQ_ISR_LOC)
{
uint32 intr_status;
uint32 range_status;
/* Read interrupt status registers */
intr_status = ADC_SAR_SEQ_SAR_INTR_MASKED_REG;
/* Check for End of Scan interrupt */
if((intr_status & ADC_SAR_SEQ_EOS_MASK) != 0u)
{
/* Read range detect status */
range_status = ADC_SAR_SEQ_SAR_RANGE_INTR_MASKED_REG;
/* Verify that the conversion result met the condition Low_Limit <= Result < High_Limit */
if((range_status & (uint32)(1ul << CH0_N)) != 0u)
{
/* Read conversion resoult */
result[CH0_N] = ADC_SAR_SEQ_GetResult16(CH0_N);
/* Set PWM compare from channel0 */
PWM_WriteCompare(result[CH0_N]);
}
/* Clear range detect status */
ADC_SAR_SEQ_SAR_RANGE_INTR_REG = range_status;
dataReady |= ADC_SAR_SEQ_EOS_MASK;
}
/* Check for Injection End of Conversion */
if((intr_status & ADC_SAR_SEQ_INJ_EOC_MASK) != 0u)
{
result[TEMP_CH] = ADC_SAR_SEQ_GetResult16(TEMP_CH);
dataReady |= ADC_SAR_SEQ_INJ_EOC_MASK;
}
/* Clear handled interrupt */
ADC_SAR_SEQ_SAR_INTR_REG = intr_status;
}
if((intr_status & ADC_SAR_SEQ_INJ_EOC_MASK) != 0u)
{
result[TEMP_CH] = ADC_SAR_SEQ_GetResult16(TEMP_CH);
dataReady |= ADC_SAR_SEQ_INJ_EOC_MASK;
}
/* Clear handled interrupt */
ADC_SAR_SEQ_SAR_INTR_REG = intr_status;
}
复制代码 这段代码写得挺乱的,就不说了。
可是我实际连上板子跑的时候,我发现,第二个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函数就成了void main()
{
ADC_SAR_SEQ_Start();
ADC_SAR_SEQ_StartConvert();
ADC_SAR_SEQ_IRQ_StartEx(ADC_SAR_SEQ_ISR_LOC);
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;
CyGlobalIntEnable;
while(1);
} 复制代码 这样再跑,我发现,丫的,终于进来了。
可是还是不对头。
我发现它进了一次就再也不会进来了。
为什么呢?
这个例程还是值得怀疑,这次我修改了一个我早就怀疑的地方。
// clear interrupt handle;
ADC_SAR_SEQ_SAR_INTR_REG &= ~ADC_SAR_SEQ_INJ_EOC_MASK ;
就是中断服务函数里的最后一句清除中断标志的语句
它原来的写法,你看到了,是这种莫名其妙很奇怪的写法
ADC_SAR_SEQ_SAR_INTR_REG = intr_status;
简直是莫名其妙。