打印
[STM8]

有關ADC使用的問題

[复制链接]
3301|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
luciengou|  楼主 | 2014-1-20 13:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 luciengou 于 2014-1-20 14:06 编辑

小弟為初學STM8的新手,用以前的概念寫STM8的程式時,出現了一點問題,請前輩指導。

我建置了像Arduino的程式架構,初始設定寫在setup(),主程式寫在loop()。
但是只要啟動了ADC_init(),loop()就不執行了,變成要把碼寫在TIM4_Int()之中。
為什麼會變這樣?

同樣的方法,在PIC中卻可以。

小弟是否哪邊設定不正確,煩請各位前輩指導。

附上我所寫的程式碼,寫得不好,請指教。

MyIARSTM8.zip

4.72 KB

沙发
yzzly| | 2014-1-20 14:02 | 只看该作者
靠,怎么都是繁体字啊?

使用特权

评论回复
板凳
luciengou|  楼主 | 2014-1-20 14:28 | 只看该作者
跨海拜師。

STM8這用得多,大師也多。

程式loop()中有個LED,會每500ms閃動一次,如果把setup()中的ADC_init()啟動了,
LED就不閃了。

而在Int.c中的TIM4_Int(),有個LED閃動,啟動會閃。以證明程式有在運作。

不知為何ADC_Init()啟動後,loop()中的程式就不跑了?

使用特权

评论回复
地板
helldata| | 2014-1-20 15:03 | 只看该作者
仿真一下,当LED不闪时,你停下来看下程序停在哪儿,应该是哪个while()那儿了。

使用特权

评论回复
5
luciengou|  楼主 | 2014-1-20 15:21 | 只看该作者
沒有喔,我從來不用死迴圈的。

很像是ADC中斷太忙,沒把CPU時間留出來,給一般程式使用。

可是這樣就很不合理呀,大家ADC中斷不也這樣用的嗎?

使用特权

评论回复
6
helldata| | 2014-1-20 15:36 | 只看该作者
你的ADC中断有没有出来还不知道,你要看下程序有没有从中断中跑出来。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
luciengou + 1 很给力!
7
luciengou|  楼主 | 2014-1-20 15:49 | 只看该作者
看來沒人去看我上傳的程式碼。

對不起大家了,我貼上我的碼,佔用點版面:

Int.c中的碼:

unsigned int ADC_Val_Int;

#pragma vector=ADC1_EOC_vector        //For ADC1 EOC Interrupt
__interrupt void ADC1_Int(void)
{
          unsigned int ADCH,ADCL;
       
    ADCH =ADC_DRH;              
    ADCL =ADC_DRL;
    ADC_Val_Int =(ADCH<<2) + ADCL ;
       
        //ADC_CR1_ADON=ON;        //Single Mode Need
}
//-----------------------
setup.c中的碼:
void ADC_Init(void)
{
          unsigned int i;
       
          ADC_CR1_ADON=0;        //A/D Converter on/off
                                        //0: Disable ADC conversion/calibration and go to power down mode.
                                        //1: Enable ADC and to start conversion
       
          ADC_CR1=0;
        ADC_CR1_SPSEL=0;//Prescaler selection(0~7)
                                        //Master Clock/2,/3,/4,/6,/8,/10,/12,/18
       
        //ADC_CR1_CONT=0;        //Continuous conversion For Single               
        ADC_CR1_CONT=1;        //Continuous conversion        For ADC Interrupt
                                        //0: Single conversion mode
                                        //1: Continuous conversion mode
       
        ADC_CR2_ALIGN=0;//Data alignment
                                        //0: Left  alignment 8MSB in ADC_DRH, 2LSB in ADC_DRL
                                        //1: Right alignment 2MSB in ADC_DRH, 8LSB in ADC_DRL
       
        ADC_CR3_DBUF=0;        //Data buffer
                                        //0: Disable
                                        //1: Enable
       
        ADC_CSR_CH=4;        //ADC Channel Select:ADC4
       
        ADC_CSR_EOCIE=ON;        //Interrupt enable for EOC  For ADC Interrupt
       
        ADC_TDRL=1;                //Schmitt trigger
                                        //0: Schmitt trigger enabled
                                        //1: Schmitt trigger disabled
       
        //ADC Module Initial
        ADC_CR1_ADON=ON;                        //A/D Converter on/off
           for(i=0;i<100;i++);              //Delay, wait for ADC
           ADC_CR1_ADON=ON;
}

使用特权

评论回复
8
helldata| | 2014-1-20 16:10 | 只看该作者
中断里面没有清标志位。

使用特权

评论回复
9
jiabin1024| | 2014-1-20 16:18 | 只看该作者
STM8不是有库函数,直接用库好了,STM8只是玩了一下,没有用在实际项目里面,是不是配置上的问题,建议多看看DATASHEET

使用特权

评论回复
10
luciengou|  楼主 | 2014-1-20 16:30 | 只看该作者
本帖最后由 luciengou 于 2014-1-20 16:37 编辑
helldata 发表于 2014-1-20 16:10
中断里面没有清标志位。

請問是這個嗎:

ADC_CSR_EOC=0;


使用特权

评论回复
11
helldata| | 2014-1-20 16:38 | 只看该作者
luciengou 发表于 2014-1-20 16:30
請問是這個嗎:

ADC_CSR_EOC=0;

这个寄存器可以位操作吗?
ADC_CSR_EOC=0;
这个是对EOC位清0吗?
这个标志位是必须要清的,要不然会总是进这个中断服务的。
另外,你ADC初始化中把连续转换改为单次转换试试。
在中断服务程序里面进入后先关中断,出来的时候再打开中断。

使用特权

评论回复
12
luciengou|  楼主 | 2014-1-20 16:59 | 只看该作者
helldata 发表于 2014-1-20 16:38
这个寄存器可以位操作吗?
ADC_CSR_EOC=0;
这个是对EOC位清0吗?

試過了,一樣無效。

程式我改了一下,現在會每秒閃一下,只是loop()中的程式碼,仍然不會執行。
關鍵程式碼,如下:
void loop(void)
{
  
          if(Button==0){
                BEEP_CSR_BEEPEN=1;
                delay_ms(200);
                BEEP_CSR_BEEPEN=0;
          }
          else BEEP_CSR_BEEPEN=0;
       
        Serial595(ADC_Val_Int);
}

void ADC_Init(void)
{
          unsigned int i;
       
          ADC_CR1_ADON=0;        //A/D Converter on/off
                                        //0: Disable ADC conversion/calibration and go to power down mode.
                                        //1: Enable ADC and to start conversion
       
          ADC_CR1=0;
        ADC_CR1_SPSEL=0;//Prescaler selection(0~7)
                                        //Master Clock/2,/3,/4,/6,/8,/10,/12,/18
       
        ADC_CR1_CONT=0;        //Single conversion
        //ADC_CR1_CONT=1;        //Continuous conversion        For ADC Interrupt
                                        //0: Single conversion mode
                                        //1: Continuous conversion mode
       
        ADC_CR2_ALIGN=0;//Data alignment
                                        //0: Left  alignment 8MSB in ADC_DRH, 2LSB in ADC_DRL
                                        //1: Right alignment 2MSB in ADC_DRH, 8LSB in ADC_DRL
       
        ADC_CR3_DBUF=0;        //Data buffer
                                        //0: Disable
                                        //1: Enable
       
        ADC_CSR_CH=4;        //ADC Channel Select:ADC4
       
        ADC_CSR_EOCIE=ON;        //Interrupt enable for EOC  For ADC Interrupt
       
        ADC_TDRL=1;                //Schmitt trigger
                                        //0: Schmitt trigger enabled
                                        //1: Schmitt trigger disabled
       
        //ADC Module Initial
        ADC_CR1_ADON=ON;                        //A/D Converter on/off
           for(i=0;i<100;i++);              //Delay, wait for ADC
           ADC_CR1_ADON=ON;
}

#pragma vector=ADC1_EOC_vector        //For ADC1 EOC Interrupt
__interrupt void ADC1_Int(void)
{
          unsigned int ADCH,ADCL;
       
    ADCH =ADC_DRH;              
    ADCL =ADC_DRL;
    ADC_Val_Int =(ADCH<<2) + ADCL ;
       
        ADC_CSR_EOC=OFF;        //EOC Clear
       
        ADC_CR1_ADON=ON;        //Single Mode Need
}

#pragma vector=TIM2_OVR_UIF_vector        //For Timer 2 Interrupt
__interrupt void TIM2_Int(void)
{  
          t4++;
       
    TIM2_SR1_UIF=0;        //Update interrupt flag
                                    // 16M/(31250*128)=4hz

        if(t4==4)
    {  
        LED=~LED;                //Question
               
                t4=0;
    }
       
}  

使用特权

评论回复
13
dragon_hn| | 2014-1-20 17:09 | 只看该作者
估计大家的ADC很少用中断吧,至少我不用。
如果怀疑ADC中断出不来,可以先把ADC中断关了试试。

使用特权

评论回复
14
helldata| | 2014-1-20 17:17 | 只看该作者
把TIM2中的LED反转去掉,加到ADC中断里面去,观察LED的状态。
单次转换的话,你需要每次打开转换。
LOOP()没有反应,也有可能是你的按键判断没有反应有关。
最好你在线调试。

使用特权

评论回复
15
luciengou|  楼主 | 2014-1-20 17:27 | 只看该作者
本帖最后由 luciengou 于 2014-1-20 17:54 编辑

和你說一件事,loop 的每個功能都有效,我有放入TIM2_Int去執行過。
都很正常

而ADC一直都有把值丟出來,在我的數字顯示器上顯示。
Buzzer也有正常叫。按鍵也有正常。

現在問題是在,為什麼loop中的程式碼不會執行。

main.c長這樣:
void main(void)
{
        //Arduino Like
        setup();
        while (1){
                loop();
        }
}

使用特权

评论回复
16
mmuuss586| | 2014-1-20 18:55 | 只看该作者
;P

使用特权

评论回复
17
luciengou|  楼主 | 2014-1-20 20:08 | 只看该作者
我找到了,helldata兄沒說錯,是沒有清除EOC的原因。

另一個重點是,ADON也不應該放在中斷程式中。

其他就是用Single Convertion時,一定要下ADON,並且給足夠時間讓ADC轉換。

不然就用Continuous Conversion,那就不用下ADON了,CPU會自己轉換。
只是Prescaler不要選太短,太忙碌ADC轉換會佔用CPU時間,會拖到自己要跑的程式時間。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

9

帖子

0

粉丝