急: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秒的周期亮灭
}
}
}
纠正下:现在的问题是没有串口中断输入时,可正常检测到3.5V并关机,若串口有数据不断输入时,则3.3V才关机,请问何原因?
页:
[1]