你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

急:stm8s串口中断与adc关机电压检测问题

[复制链接]
zerg_aoo 提问时间:2016-9-21 14:58 /
本帖最后由 zerg_aoo 于 2016-9-21 15:03 编辑

1、芯片及开发环境:STM8S003和IAR开发环境;
2、主要问题:程序需实现3.5V以下关机功能,若每12秒未收到串口输入的数据(数据是5秒发一次的字符a),否则闪断关机脚,实现RESET。现在的问题是串口没有中断输入时,可正常检测到3.5V并关机,若串口有数据不断输入时,则3.3V才关机,请问何原因?查到较多关于串口中断,定时器,串口过载错误等资料,一个星期了始终没有解决。项目是一个车载跟踪器的项目,马上要出货了,比较着急,求助大家帮忙看看,谢谢了!
3、main.c完整程序如下:
#include<iostm8s103f3.h>

unsigned int ADCData;
unsigned int second_count;
unsigned int uart_count;
unsigned char powerflag;

#define   ONOFF_ON()    PC_ODR_bit.ODR7 = 0
#define   ONOFF_OFF()   PC_ODR_bit.ODR7 = 1

#define   MX6_POR_B_ON()    PC_ODR_bit.ODR5 = 0
#define   MX6_POR_B_OFF()   PC_ODR_bit.ODR5 = 1

#define   Voltage_3V7   0x02EE  //3.75v*22k/(22k+12k)=2.43v(%d0750)
#define   Voltage_3V5   0x02B8  //3.50v*22k/(22k+12k)=2.26v(%d0696)

/*******************************************************************************
**函数名称:void delay(unsigned int ms)
**功能描述:大概延时
**入口参数:unsigned int ms   输入大概延时数值
**输出:无
*******************************************************************************/
void delay(unsigned int ms)
{
  unsigned int x , y;
  for(x = ms; x > 0; x--)           /*通过一定周期循环进行延时*/
    for(y = 1000 ; y > 0 ; y--);
}

/*******************************************************************************
**函数名称:ONOFF_Init()
**功能描述:初始化ONOFF引脚
**入口参数:无
**输出:无
*******************************************************************************/
void ONOFF_Init()
{
  PC_DDR_bit.DDR7 = 1;    //设置端口PC->7的输入输出方向寄存器为输出方向
  PC_CR1_bit.C17 = 1;     //PC->7为推挽输出
  PC_CR2_bit.C27 = 1;     //PC->7是输出速度最快为10MHz
}

/*******************************************************************************
**函数名称:MX6_POR_B_Init()
**功能描述:初始化MX6_POR_B控制引脚
**入口参数:无
**输出:无
*******************************************************************************/
void MX6_POR_B_Init()
{
  PC_DDR_bit.DDR5 = 1;    //设置端口PC->5的输入输出方向寄存器为输出方向
  PC_CR1_bit.C15 = 1;     //PC->5为推挽输出
  PC_CR2_bit.C25 = 1;     //PC->5是输出速度最快为10MHz
}

/*******************************************************************************
**函数名称:void TIM1_Init()
**功能描述:定时器1参数初始化
**入口参数:无
**输出:无
*******************************************************************************/
void TIM1_Init()
{
  TIM1_CR1_bit.CEN = 0;          //stop tim1
  
  //设置定时器的时钟为 =  16000000 / (psc + 1) = 16000000 / 400 = 40000Hz
  TIM1_PSCRH = 399 / 256;        //设置定时器1的预分频数值为 psc  = 399 + 1
  TIM1_PSCRL = 399 % 256;        //
  
  TIM1_CR1_bit.CMS = 0;          //设置定时器1的边沿对齐模式
  TIM1_CR1_bit.DIR = 0;          //计数模式为向上计数 UP Count
  
  //设置定时器1计数40000次 = 1秒时间产生中断
  TIM1_ARRH = 40000 / 256;       //高八位
  TIM1_ARRL = 40000 % 256;       //低八位
  TIM1_CNTRH = 0x0000;           //清除计数寄存器的高八位
  TIM1_CNTRL = 0x0000;           //清除计数寄存器的低八位
  TIM1_IER_bit.UIE = 1;          //使能更新中断
  TIM1_CR1_bit. ARPE = 1;        //设置允许自动更新
  TIM1_CR1_bit. CEN = 1;         //使能定时器1开始计数
}

/*******************************************************************************
**函数名称:void UART1_Init(unsigned int baudrate)
**功能描述:初始化USART模块
**入口参数:unsigned int baudrate  -> 设置串口波特率
**输出:无
*******************************************************************************/
void UART1_Init(unsigned int baudrate)
{   
  unsigned int baud;           
  
  baud = 16000000 / baudrate;    //设定串口相应波特率与串口时钟的分频数
  
  //先写BRR2 , 再写BRR1
  UART1_BRR2 = ((unsigned char)((baud & 0xf000) >> 8 )) | ((unsigned char)(baud & 0x000f));       //先写波特比率的高4位与低4位
  UART1_BRR1 =  ((unsigned char)((baud & 0x0ff0) >> 4));                                          //后写波特比率的中间8位
  
  UART1_CR1_bit.UART0 = 0;        //使能UART0
  UART1_CR2_bit.RIEN = 1;         //使能中断接收
  UART1_CR2_bit.TEN = 1;          //使能发送
  UART1_CR2_bit.REN = 1;          //接收使能
}

/*******************************************************************************
**函数名称:void Uart_SendData(unsigned char  data)
**功能描述:向串口发送寄存器写入一个字节数据
**入口参数:unsigned char  data
**输出:无
*******************************************************************************/
void Uart_SendData(unsigned char data)
{
  while(!(UART1_SR&0X80));      //判断发送数据寄存器是否为空
  UART1_DR = data;              //向发送寄存器写入数据
}

/*******************************************************************************
**函数名称:void ADC_Init()
**功能描述:初始化ADC
**入口参数:无
**输出:无
*******************************************************************************/
void ADC_Init()
{
  PD_DDR_bit.DDR3 = 0;     //设置PD->3 为输入
  PD_CR1_bit.C13 = 0;      //设置为悬空输入
  PD_CR2_bit.C23 = 0;      //设置中断禁止
  
  ADC_CR1_bit.SPSEL = 3;   //fmaster / 18 = 16MHZ / 18 = 888888HZ
  ADC_CR2_bit.ALIGN = 1;   //RIGHT ALIGN
  ADC_CSR_bit.CH = 4;      //SELECT AIN4
  
  ADC_CR1_bit.ADON = 1;    //启动ADC
}

/*******************************************************************************
**函数名称:void ADC_Data_Read(unsigned int *AD_Value)
**功能描述:读取ADC完成一次模数转换结果
**入口参数:unsigned int *AD_Value
            *AD_Value ->读取ADC采样数据的指针
**输出:无
*******************************************************************************/
void ADC_Data_Read(unsigned int *AD_Value)
{
   ADC_CR1_bit.ADON = 1;         //启动ADC
  
   while(ADC_CSR_bit.EOC == 0);  //等待转换结束
  *AD_Value = ADC_DRH;          //先读取高8位
  *AD_Value = (unsigned int)((*AD_Value << 8) + ADC_DRL);   //高8位与低8位相加,凑成16位数据
}

/*******************************************************************************
**函数名称:void IWDG_Init()
**功能描述:初始化独立看门狗
**入口参数:无
**输出:无
*******************************************************************************/
void IWDG_init(void)
{
  IWDG_KR = 0xCC;  //启动IWDG
  IWDG_KR = 0x55;  //解除 PR 及 RLR 的写保护
  IWDG_RLR = 0xFF; //看门狗计数器重装载数值        
  IWDG_PR = 0x06; //分频系数为256,最长超时时间为:1.02S
  IWDG_KR = 0xAA; //刷新IDDG,避免产生看门狗复位,同时恢复 PR 及 RLR 的写保护状态
}

/*******************************************************************************
**函数名称:void Power_Manage()
**功能描述:MX6电源控制函数
**入口参数:无
**输出:无
*******************************************************************************/
void Power_Manage(void)
{
  ADC_Data_Read(&ADCData);  //读取ADC的采样数值
  if(ADCData >= Voltage_3V7) //如果电压大于3.7V,则打开MX6电源
    {
     delay(50); //延时去抖动
     ADC_Data_Read(&ADCData);  //读取ADC的采样数值
     if(ADCData >= Voltage_3V7)
       {
         MX6_POR_B_ON();  //开启MX6电源
         powerflag=1;     //置MX6电源标志位为1
       }
    }
  
   else if((ADCData > 0)&&(ADCData <= Voltage_3V5)) //如果电压为3.5v以下,关掉MX6电源
    {
     delay(50); //延时去抖动
     ADC_Data_Read(&ADCData);  //读取ADC的采样数值
     if((ADCData > 0)&&(ADCData <= Voltage_3V5))
       {
         MX6_POR_B_OFF(); //关MX6电源
         powerflag=0;    //置MX6电源标志位为0
       }
    }
   
   else
    {;}
    delay(50); //延时去抖动
}

/*    主函数    */
int main(void)
{
  asm("sim");          //关闭系统总中断
  CLK_CKDIVR = 0x00;   //CPUDIV = 1 HSIDIV = 1  内部时钟 = 16Mhz
  UART1_Init(9600);    //调用串口初始化函数,并设置波特率为9600 bps
  TIM1_Init();         //调用定时器1初始化函数
  ADC_Init();          //调用ADC初始化函数
  
  ONOFF_Init();        //初始化NOOFF控制引脚
  ONOFF_ON();          //默认关闭imx6ul睡眠控制脚
  
  MX6_POR_B_Init();    //初始化MX6_POR_B控制引脚
  MX6_POR_B_ON();      //默认开启imx6ul电源
  powerflag=1;         //清除MX6电源标志位

  IWDG_init();         //始化独立看门狗
  
  asm("rim");          //打开系统总中断
  
  while(1)
  {
    Power_Manage();
    IWDG_KR = 0xAA;  //刷新IDDG,避免产生看门狗复位,同时恢复 PR 及 RLR 的写保护状态
  }
}

/*******************************************************************************
**函数名称:__interrupt void UART1_RX_RXNE(void)
**功能描述:串口接收数据中断服务函数
**入口参数:无
**输出:无
*******************************************************************************/
#pragma vector = 0x14      //设置串口接收中断向量号 = 0X14
__interrupt void UART1_RX_RXNE(void)
{
  unsigned char ch1;
  UART1_SR_RXNE = 1;    //清除中断标志
  uart_count++;         //中断使 uart_count++++ 做加法,记录产生的中断次数
  if(UART1_SR_OR_LHE)  //发生过载错误,顺序读UART1_SR,UART1_DR来清UART1_SR_OR_LHE位
  {
    ch1 = UART1_SR;
    ch1 = UART1_DR;
  }
  
  else
  {
   ch1 = UART1_DR;
  }
  Uart_SendData(ch1);   //把接收到的数据再通过串口发送出去
  return;
}

/*******************************************************************************
**函数名称:__interrupt void TIM1_UPDATE_IRQHandler(void)
**功能描述:定时器1重载更新中断服务函数
**入口参数:无
**输出:无
*******************************************************************************/
#pragma vector = TIM1_OVR_UIF_vector      //设置定时器1重载的中断向量号 = 13
__interrupt void TIM1_UPDATE_IRQHandler(void)
{
  TIM1_SR1_bit.UIF = 0;    //清除中断标志
  second_count++;          //中断使 second_count++ 做加法,记录1秒产生的中断次数
  if(second_count >= 12)   //记录达到12秒,即12秒(与MX6的kernel启动时间相关)
  {
    second_count = 0;     //复位记录TIM1中断次数
    if((uart_count == 0)&&(powerflag==1))
     {
       MX6_POR_B_OFF(); //关MX6电源
       delay(500);
       MX6_POR_B_ON();  //打开MX6电源
     }
   
    else
    {  
      uart_count = 0;  //复位记录串口中断次数
      //PC_ODR ^= 0x80;  //对LED2进行异或取反,使LED2以1秒的周期亮灭
    }
  }
}
收藏 评论1 发布时间:2016-9-21 14:58

举报

1个回答
zerg_aoo 回答时间:2016-9-21 15:00:17
纠正下:现在的问题是没有串口中断输入时,可正常检测到3.5V并关机,若串口有数据不断输入时,则3.3V才关机,请问何原因?

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版