您的位置 首页 新品

关于STM8S ADC脚与其它功用复用时的问题

之前写过一篇关于STM8S芯片GPIO脚复用AD功能后无法回到GPIO状态的小文,介绍STM8S芯片的ADC应用时相关施密特触发器未适时开关而导致的问题。大致内容就是某一GPIO口被复用为

  之前写过一篇关于STM8S芯片GPIO脚复用AD功用后无法回到GPIO状况的小文,介绍STM8S芯片的ADC运用时相关施密特触发器未当令开关而导致的问题。

  大致内容便是某一GPIO口被复用为AD输入脚做相关AD检测。之后,把该脚AD功用禁用掉,再装备切换为带下降沿触发的外部中止触发脚,让其作为芯片休眠唤醒脚。

  奇怪的是,那样设置后底子无法唤醒。即便不做休眠,做好切换装备后,直接检查该脚的IDR位的电平,不论外部输入怎么,发现对应IDR位一直提示为0.

  后来找到原因是跟那个施密特触发器的装备有关。或许有人觉得该问题是钻牛角尖,其实,也不尽然。究竟运用需求是形形色色的,遇到的问题往往也是五光十色,问题不论巨细折磨起人来也是不分男女老少的。

  这儿再次共享个相似论题 ,期望能让见到本文的人有所启示。工程师反应底子状况如下:

  运用STM8S芯片开发。由于TIM1/2都用做PWM了,所以用TIM4来做底子守时。TIM4正常中止,UART1串口发送正常,便是串口接纳中止进不去。但只要把 TIM4_initialzation();屏蔽掉,串口立刻正常中止接纳,一旦翻开TIM4,串口就接纳不了,其它功用都正常。

  上面是该工程师对症状的底子描绘和初步判别。【当然,调试遇到费事时分的判别不免有误差,误差巨细因人因景不同,有时乃至彻底误判。】

  下面是他的主循环代码【为了排版和阅览,做了些删减】。

  int main( void )

  {

  CLK_DeInit(); //寄存器复位

  CLK_HSICmd(ENABLE); //内部高速时钟使能

  CLK_HSIPrescalerConfig( ); //分频

  GPIO_initialzation();

  uart_initialzation();

  PWM1_initialzation();

  PWM2_initialzation();

  TIM4_initialzation(); //TIM4初始化

  enableInterrupts();//* 敞开总中止 */

  Ts_cnt = 1000;

  Ls_cnt = 500;

  while(1)

  {

  PLED_flash(499); //LED 闪耀

  relay_control(); //继电器操控

  CCT_calculate();//获取相关AD值

  send_information();//输出提示信息

  if(Flag_rec)

  {

  。。。。。。【略】

  }

  }

  }

  现在的状况是当注释掉上面的 TIM4_initialzation();句子后,UART-RX接纳中止就正常。

  TIM4仅仅做底子时钟,不触及外面其它硬件,最大或许是二者中止优先级有抵触导致UART-RX的正常接纳。但当把UART-RX中止优先级调高于TIM4的更新中止时问题并无好转。

  但现实又确实显示出TIM4的中止跟UART-RX接纳有联系。

  TIM4、UART1初始化代码仅仅些各种相关底子装备,不跟其他外设有相关。无妨看看TIM4、UART1中止服务程序里能否找到些蛛丝马迹。

  INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler,23)

  {

  TIM4_ClearITPendingBit(TIM4_IT_UPDATE);

  ms_cnt++;//LED FLASH

  Ts_cnt++; //AD sample

  Ls_cnt++; //relay control

  uart_cnt++;//send information

  PWM2_duty_setting(Ts_cnt);

  pwm1_correct_cnt++;

  if(pwm1_correct_cnt > 100)

  {

  pwm1_correct_cnt = 0;

  if(pwm1_cnt > CCT_target)

  pwm1_cnt–;

  else

  pwm1_cnt++;

  PWM1_duty_setting(pwm1_cnt);

  }

  }

  INTERRUPT_HANDLER(UART1_RX_IRQHandler,18)

  {

  static uint8_t index = 0;

  UART1_ClearITPendingBit(UART1_IT_RXNE);

  recived_data[index] = UART1_ReceiveData8(); //读数据

  if(recived_data[0] == 0x41)

  {

  index++;

  if((index > 7)&&(recived_data[7] == 0x0d))

  {

  index = 0;

  Flag_rec = 1;

  }

  }

  else

  {

  index = 0;

  recived_data[0] = 0;

  }

  }

  从TIM4的中止服务程序里呈现了好几个全局变量,看看这些全局变量哪些函数会用到。由于TIM4的主要功用便是计数守时,下面几个计时变量肯定是给他人用的。

  ms_cnt++;//LED FLASH

  Ts_cnt++; //AD sample

  Ls_cnt++; //relay control

  uart_cnt++;//send information

  问题到这儿,持续往下查就需要耐性了。客户代码不杂乱,用到的外设模块也不多,主循环里也就下面几个函数,一个个函数模块进行排查。

  PLED_flash(499); //LED闪耀

  relay_control(); //继电器操控

  CCT_calculate();//做AD转化

  send_information();//输出提示信息

  后来发现TIM4坚持作业的一起屏蔽CCT_calculate();,UART-RX能正常接纳。看来TIM4并非是影响UART接纳的首恶。不过CCT_calculate()的运转仍是跟TIM4中止有关,有个变量TS_CNT是在TIM4中止里进行累加的。

  看看下面CCT_calculate()的代码,里边有个条件判别,即if(Ts_cnt > 1000)的判别。

  voidCCT_calculate(void)

  {

  if(Ts_cnt> 1000)

  {

  Ts_cnt = 0;

  T_ad = Get_ADCCH_Value(Ts_channel);

  T_degree = cal_temp(T_ad)-11;

  。。。。。

  }

  }

  假如TIM4被屏蔽不作业,TS_CNT就不会得到累加而大于1000然后往下履行Get_ADCCH_Value();函数。该Get_ADCCH_Value();函数对ADC做初始化之后履行AD转化并获取相关AD值。

  正是在ADC初始化代码里有对相关ADC通道对应脚的施密特触发器做了禁用装备。并且该ADC通道脚跟UART-RX脚又是复用的,费事就此产生了。

  

 

  在STM8MCU的GPIO 的各IO模块里有个施密特触发器,经过寄存器ADC_TDR操控其开和关。默许状况下是翻开的,IO脚的信号能够自在经过它进到输入寄存器或其它外设模块。

  假如某管脚做AD模仿输入时,主张经过ADC_TDR将相应的施密特触发器封闭,意图是为了下降GPIO的功耗。如下图所示,当施密特触发器被封闭后,不论外部引脚电平怎么改变,它的输出恒定为0。

  

 

  结合到本事例中的问题,由于他在AD转化函数中初始化AD时封闭了该施密特触发器,该脚又复用为UART-RX,此刻RX信号底子进不到UART接纳模块中,不能产生UART接纳中止也就自然而然了。

  后来当它翻开施密特触发器后,URAT-RX接纳也就正常了。

  明显,客户最早以为的TIM4影响UART-RX是个幻觉。由于它是每隔一守时刻才去做AD转化,一起做些AD初始化装备。假如TIM4封闭了,相应的时刻条件不成立也就不去做AD转化,也就不会禁用施密特触发器,从而就不会产生UART-RX失利的状况。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/115067.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部