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

急: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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版