AI8051U启用内部低速LIRC时为什么程序会死机呢?
3 天前 来自 ssfnpl 发布 @ 综合讨论
各位大佬,能帮看下这是什么问题吗? 程序框架用的ISP_AICube生成的
下面的程序读取MPU6050数据并通过串口1发送,当使用内部时钟晶振并启用RTC时程序就死机了,表现为P2口的LED停止了,串口也不发送数据了,死机时USB的查询模式一直能正常下载程序 ,如果不对RTC_Init(); //RTC进行初始化,程序就能一直在跑。串口数据每20毫秒发送都不会出现死机。
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2025-06-04) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
/***************************SCL P15 SDA P14********************************/
#include "config.h" //默认已包含stdio.h、intrins.h、ai_usb.h等头文件
#include "MPU6050.h"
int LED_tibo = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
int inx;
MPU6050_Dat mpu_data;//结构体变量 保存MPU6050数据
void send_char (unsigned char c); //GB 2312发送一个字符
void send_string (unsigned char *s); //GB 2312 发送字符串
void MPU6050_TO_UART1(void);
extern bit timer_bit_32;
extern bit timer_bit_1sec;
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
char RTC_DATA;
u8 a;
// char UART1_DAT;
// u16 temp_raw;
// u8 who;
// Delay5us();
SYS_Init();
while (1)
{
USBLIB_OUT_Done(); //查询方式处理USB接收的数据
P2 = LED_tibo;
inx++;
P2 = ~P2;
if(inx >=8)
{
inx = 0;
a++;
}
delay_ms(500);
// mpu_id = Read_MPU6050_WHO_AM_I();
/* if(mpu_id == 0x68)
{
send_string("通讯地址正常");
} else {send_string("通讯地址异常\r\n");}
*/
/*
if(Read_MPU6050_Dat(&mpu_data))
{
sprintf(UART1_DAT,"Accel: X=%d,Y=%d,Z=%d\r\n",
mpu_data.accel_x,mpu_data.accel_y,mpu_data.accel_z);
send_string(UART1_DAT);
sprintf(UART1_DAT,"Temp: %d ->d %.2f℃\c\n",
mpu_data.temp,MPU6050_Temp_Convert(mpu_data.temp));
send_string(UART1_DAT);
sprintf(UART1_DAT,"Gyro: X=%d,Y=%d,Z=%d\r\n",
mpu_data.gyro_x,mpu_data.gyro_y,mpu_data.gyro_z);
send_string(UART1_DAT);
} //else { //send_string("MPU6050");
// send_string("MPU6050读取失败!\r\n");}
*/
if(timer_bit_1sec == 1)
{ timer_bit_1sec = 0;
send_string ("不良人“境心魔-旺仔”\r\n"); //GB 2312 发送字符串
send_string ("候卿个老 6\r\n");
send_string ("AI-8051U-内置RTC时钟\r\n");
sprintf(RTC_DATA,"20%d年%d月%d日%d时%d分%d秒",
RTCYEAR,RTCMONTH,RTCDAY,RTCHOUR,RTCMIN,RTCSEC);
send_string(RTC_DATA);
send_string("\r\n");
}
MPU6050_TO_UART1();
}
}
////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramFastest(); //设置最快速度访问内部XDATA
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
P0M0 = 0x00; P0M1 = 0x00; //初始化P0口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //初始化P1口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //初始化P2口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //初始化P3口为准双向口模式
P4M0 = 0x00; P4M1 = 0x00; //初始化P4口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //初始化P5口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //初始化P6口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //初始化P7口为准双向口模式
CLK_Init(); //时钟模块初始化
UART1_Init(); //串口1初始化
RTC_Init(); //RTC初始化
// I2C_Init(); //I2C初始化
InitMPU6050();
USBLIB_Init(); //USB库初始化
//<<AICUBE_USER_INITIAL_CODE_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_INITIAL_CODE_END>>
EnableGlobalInt(); //使能全局中断
}
////////////////////////////////////////
// 微秒延时函数
// 入口参数: us (设置延时的微秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_us(uint16_t us)
{
do
{
NOP(18); //(MAIN_Fosc + 500000) / 1000000 - 6
} while (--us);
}
////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
uint16_t i;
do
{
i = MAIN_Fosc / 6000;
while (--i);
} while (--ms);
}
////////////////////////////////////////
// 串口1中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void UART1_ISR(void) interrupt UART1_VECTOR
{
//<<AICUBE_USER_UART1_ISR_CODE1_BEGIN>>
// 在此添加中断函数用户代码
if (UART1_CheckTxFlag()) //判断串口发送中断
{
UART1_ClearTxFlag(); //清除串口发送中断标志
}
if (UART1_CheckRxFlag()) //判断串口接收中断
{
UART1_ClearRxFlag(); //清除串口接收中断标志
}
//<<AICUBE_USER_UART1_ISR_CODE1_END>>
}
////////////////////////////////////////
// 时钟初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void CLK_Init(void)
{
CLK_LIRC_Enable(); //启动内部低速LIRC RTC
CLK_LIRC_WaitStable(); //等待振荡器稳定 RTC
CLK_SYSCLK_Divider(10); //切换主时钟前先将系统时钟降频
HIRC_24M(); //选择内部预置的频率
CLK_MCLK_HIRC(); //选择内部高精度HIRC作为主时钟
CLK_MCLK2_BYPASS(); //旁路MCLK2,直接使用MCLK选择
CLK_SYSCLK_Divider(1); //设置系统时钟分频系数
CLK_HSIOCK_MCLK(); //选择MCLK主时钟作为高速外设时钟源
CLK_HSIOCK_Divider(1); //设置高速外设时钟预分频系数
CLK_SPICLK_Divider(1); //设置SPI时钟预分频系数
CLK_I2SCLK_Divider(1); //设置I2S时钟预分频系数
CLK_PWMACLK_Divider(1); //设置PWMA时钟预分频系数
CLK_PWMBCLK_Divider(1); //设置PWMB时钟预分频系数
CLK_TFPUCLK_Divider(1); //设置TFPU时钟预分频系数
//<<AICUBE_USER_CLOCK_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_CLOCK_INITIAL_END>>
}
////////////////////////////////////////
// 串口1初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void UART1_Init(void)
{
#ifdef BAUDRATE
#undef BAUDRATE
#endif
#define BAUDRATE (115200)
#define T2_RELOAD (65536 - (SYSCLK / BAUDRATE + 2) / 4)
UART1_SwitchP3637(); //设置串口数据端口: RxD (P3.6), TxD (P3.7)
UART1_Timer2BRT(); //选择定时器2作为串口1波特率发生器
TIMER2_TimerMode(); //设置定时器2为定时模式
TIMER2_1TMode(); //设置定时器2为1T模式
TIMER2_SetPrescale(0); //设置定时器2的8位预分频
TIMER2_SetReload16(T2_RELOAD); //设置定时器2的16位重载值
TIMER2_Run(); //定时器2开始运行
UART1_EnableRx(); //使能串口1接收数据
UART1_Mode1(); //设置串口1为模式1 (8位数据可变波特率)
UART1_SetIntPriority(3); //设置中断为最高优先级
UART1_EnableInt(); //使能串口1中断
//<<AICUBE_USER_UART1_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_UART1_INITIAL_END>>
}
/***********************************************************************/
#if 0
////////////////////////////////////////
// I2C初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void I2C_Init(void)
{
I2C_SwitchP1415(); //选择I2C数据口: SCL(P1.5), SDA(P1.4)
I2C_MasterMode(); //设置I2C为主机模式
I2C_SetClockDivider(13); //设置I2C为主机模式时钟
I2C_Enable(); //使能I2C功能
下面的程序读取MPU6050数据并通过串口1发送,当使用内部时钟晶振并启用RTC时程序就死机了,表现为P2口的LED停止了,串口也不发送数据了,死机时USB的查询模式一直能正常下载程序 ,如果不对RTC_Init(); //RTC进行初始化,程序就能一直在跑。串口数据每20毫秒发送都不会出现死机。

//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2025-06-04) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
/***************************SCL P15 SDA P14********************************/
#include "config.h" //默认已包含stdio.h、intrins.h、ai_usb.h等头文件
#include "MPU6050.h"
int LED_tibo = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
int inx;
MPU6050_Dat mpu_data;//结构体变量 保存MPU6050数据
void send_char (unsigned char c); //GB 2312发送一个字符
void send_string (unsigned char *s); //GB 2312 发送字符串
void MPU6050_TO_UART1(void);
extern bit timer_bit_32;
extern bit timer_bit_1sec;
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
char RTC_DATA;
u8 a;
// char UART1_DAT;
// u16 temp_raw;
// u8 who;
// Delay5us();
SYS_Init();
while (1)
{
USBLIB_OUT_Done(); //查询方式处理USB接收的数据
P2 = LED_tibo;
inx++;
P2 = ~P2;
if(inx >=8)
{
inx = 0;
a++;
}
delay_ms(500);
// mpu_id = Read_MPU6050_WHO_AM_I();
/* if(mpu_id == 0x68)
{
send_string("通讯地址正常");
} else {send_string("通讯地址异常\r\n");}
*/
/*
if(Read_MPU6050_Dat(&mpu_data))
{
sprintf(UART1_DAT,"Accel: X=%d,Y=%d,Z=%d\r\n",
mpu_data.accel_x,mpu_data.accel_y,mpu_data.accel_z);
send_string(UART1_DAT);
sprintf(UART1_DAT,"Temp: %d ->d %.2f℃\c\n",
mpu_data.temp,MPU6050_Temp_Convert(mpu_data.temp));
send_string(UART1_DAT);
sprintf(UART1_DAT,"Gyro: X=%d,Y=%d,Z=%d\r\n",
mpu_data.gyro_x,mpu_data.gyro_y,mpu_data.gyro_z);
send_string(UART1_DAT);
} //else { //send_string("MPU6050");
// send_string("MPU6050读取失败!\r\n");}
*/
if(timer_bit_1sec == 1)
{ timer_bit_1sec = 0;
send_string ("不良人“境心魔-旺仔”\r\n"); //GB 2312 发送字符串
send_string ("候卿个老 6\r\n");
send_string ("AI-8051U-内置RTC时钟\r\n");
sprintf(RTC_DATA,"20%d年%d月%d日%d时%d分%d秒",
RTCYEAR,RTCMONTH,RTCDAY,RTCHOUR,RTCMIN,RTCSEC);
send_string(RTC_DATA);
send_string("\r\n");
}
MPU6050_TO_UART1();
}
}
////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramFastest(); //设置最快速度访问内部XDATA
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
P0M0 = 0x00; P0M1 = 0x00; //初始化P0口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //初始化P1口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //初始化P2口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //初始化P3口为准双向口模式
P4M0 = 0x00; P4M1 = 0x00; //初始化P4口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //初始化P5口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //初始化P6口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //初始化P7口为准双向口模式
CLK_Init(); //时钟模块初始化
UART1_Init(); //串口1初始化
RTC_Init(); //RTC初始化
// I2C_Init(); //I2C初始化
InitMPU6050();
USBLIB_Init(); //USB库初始化
//<<AICUBE_USER_INITIAL_CODE_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_INITIAL_CODE_END>>
EnableGlobalInt(); //使能全局中断
}
////////////////////////////////////////
// 微秒延时函数
// 入口参数: us (设置延时的微秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_us(uint16_t us)
{
do
{
NOP(18); //(MAIN_Fosc + 500000) / 1000000 - 6
} while (--us);
}
////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
uint16_t i;
do
{
i = MAIN_Fosc / 6000;
while (--i);
} while (--ms);
}
////////////////////////////////////////
// 串口1中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void UART1_ISR(void) interrupt UART1_VECTOR
{
//<<AICUBE_USER_UART1_ISR_CODE1_BEGIN>>
// 在此添加中断函数用户代码
if (UART1_CheckTxFlag()) //判断串口发送中断
{
UART1_ClearTxFlag(); //清除串口发送中断标志
}
if (UART1_CheckRxFlag()) //判断串口接收中断
{
UART1_ClearRxFlag(); //清除串口接收中断标志
}
//<<AICUBE_USER_UART1_ISR_CODE1_END>>
}
////////////////////////////////////////
// 时钟初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void CLK_Init(void)
{
CLK_LIRC_Enable(); //启动内部低速LIRC RTC
CLK_LIRC_WaitStable(); //等待振荡器稳定 RTC
CLK_SYSCLK_Divider(10); //切换主时钟前先将系统时钟降频
HIRC_24M(); //选择内部预置的频率
CLK_MCLK_HIRC(); //选择内部高精度HIRC作为主时钟
CLK_MCLK2_BYPASS(); //旁路MCLK2,直接使用MCLK选择
CLK_SYSCLK_Divider(1); //设置系统时钟分频系数
CLK_HSIOCK_MCLK(); //选择MCLK主时钟作为高速外设时钟源
CLK_HSIOCK_Divider(1); //设置高速外设时钟预分频系数
CLK_SPICLK_Divider(1); //设置SPI时钟预分频系数
CLK_I2SCLK_Divider(1); //设置I2S时钟预分频系数
CLK_PWMACLK_Divider(1); //设置PWMA时钟预分频系数
CLK_PWMBCLK_Divider(1); //设置PWMB时钟预分频系数
CLK_TFPUCLK_Divider(1); //设置TFPU时钟预分频系数
//<<AICUBE_USER_CLOCK_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_CLOCK_INITIAL_END>>
}
////////////////////////////////////////
// 串口1初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void UART1_Init(void)
{
#ifdef BAUDRATE
#undef BAUDRATE
#endif
#define BAUDRATE (115200)
#define T2_RELOAD (65536 - (SYSCLK / BAUDRATE + 2) / 4)
UART1_SwitchP3637(); //设置串口数据端口: RxD (P3.6), TxD (P3.7)
UART1_Timer2BRT(); //选择定时器2作为串口1波特率发生器
TIMER2_TimerMode(); //设置定时器2为定时模式
TIMER2_1TMode(); //设置定时器2为1T模式
TIMER2_SetPrescale(0); //设置定时器2的8位预分频
TIMER2_SetReload16(T2_RELOAD); //设置定时器2的16位重载值
TIMER2_Run(); //定时器2开始运行
UART1_EnableRx(); //使能串口1接收数据
UART1_Mode1(); //设置串口1为模式1 (8位数据可变波特率)
UART1_SetIntPriority(3); //设置中断为最高优先级
UART1_EnableInt(); //使能串口1中断
//<<AICUBE_USER_UART1_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_UART1_INITIAL_END>>
}
/***********************************************************************/
#if 0
////////////////////////////////////////
// I2C初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void I2C_Init(void)
{
I2C_SwitchP1415(); //选择I2C数据口: SCL(P1.5), SDA(P1.4)
I2C_MasterMode(); //设置I2C为主机模式
I2C_SetClockDivider(13); //设置I2C为主机模式时钟
I2C_Enable(); //使能I2C功能
免责声明:
本平台旨在开源共享精神,请勿发布敏感信息,任何违法信息我们将移交公安机关;