zerg_aoo 发表于 2016-9-21 14:58:20

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

本帖最后由 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 chardata)
**功能描述:向串口发送寄存器写入一个字节数据
**入口参数:unsigned chardata
**输出:无
*******************************************************************************/
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秒的周期亮灭
    }
}
}

zerg_aoo 发表于 2016-9-21 15:00:17

纠正下:现在的问题是没有串口中断输入时,可正常检测到3.5V并关机,若串口有数据不断输入时,则3.3V才关机,请问何原因?
页: [1]
查看完整版本: 急:stm8s串口中断与adc关机电压检测问题