用串口调试助手调试的,发送命令后返回数据到串口助手上。裸机时,发送命令01 04 00 00 00 06 70 08,回01 04 0C 00 A2 00 A3 00 A2 00 A1 21 3D 14 D0 DB 85。发完立马回完。但是加入了UCOSII后,能够返回,但是回数据有一卡一卡的感觉,一帧数据分几次回完,好像发生了任务切换,但是我看了我的代码,不应该会这个时候任务切换啊,请大家帮忙看看。下面是部分代码:
//设置任务优先级
#define START_TASK_PRIO 10 //开始任务的优先级设置为最低
//设置任务堆栈大小
#define START_STK_SIZE 64
//任务堆栈
OS_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *pdata);
//Modebus任务
//设置任务优先级
#define MODBUS_TASK_PRIO 5
//设置任务堆栈大小
#define MODBUS_STK_SIZE 64
//任务堆栈
OS_STK MODBUS_TASK_STK[MODBUS_STK_SIZE];
//任务函数
void modbus_task(void *pdata);
//数据采集任务
//设置任务优先级
#define COLLECT_TASK_PRIO 3
//设置任务堆栈大小
#define COLLECT_STK_SIZE 64
//任务堆栈
OS_STK COLLECT_TASK_STK[COLLECT_STK_SIZE];
//任务函数
void collect_task(void *pdata);
OS_EVENT * msg_collect; //消息邮箱事件块指针
int main(void)
{
SystemInit();
delay_init(); //延时初始化
NVIC_Configuration();
uart_init(9600);
Ctrl_EN = 1;
LED_Init();
FM24CLXX_Init();
SPI1_ADS1220_Init();
EXTI4_Init(); //ADS1220的数据准备脚配置成下降沿中断触发,屏蔽该句可变为管脚电平检测判断
IOPort_Init();
SPI2_CC2520_Init();
CC2520_VREG_EN = 1;
CC2520_Init();
CC2520_SetRxMode();
//FCF帧控制域(2字节) + DSN(1字节) + ADDR最大地址(20字节) + FP帧负载(n) + FCS(2个字节)
CC2520_PSDU[0] = 23+12+2;
while(FM24CLXX_Check())//检测不到24CL64
{
}
FM24CLXX_Write(0,(u8*)TEXT_Buffer,SIZE);
FM24CLXX_Read(0,datatemp,SIZE);
printf("datatemp = %s",datatemp);
OSInit(); //初始化UCOSII
OSTaskCreate(start_task,(void *)0,(OS_STK *)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO );//创建起始任务
OSStart();
}
void start_task(void *pdata)
{
u8 indication = 0;
OS_CPU_SR cpu_sr=0; //采用的是方法三来开关中断的,cpu_sr用来存放CPU状态寄存器用的
pdata = pdata;
msg_collect=OSMboxCreate((void*)0); //创建消息邮箱
// sem_modbus=OSSemCreate(0); //创建消息量
if(PowerSelect_Indication) //判断供电方式
{
delay_ms(5);
if(PowerSelect_Indication) indication = 1;
}
OS_ENTER_CRITICAL(); //进入临界区(无法被中断打断)
OSTaskCreate(modbus_task,(void *)0,(OS_STK*)&MODBUS_TASK_STK[MODBUS_STK_SIZE-1],MODBUS_TASK_PRIO);
OSTaskCreate(collect_task,(void *)0,(OS_STK*)&COLLECT_TASK_STK[COLLECT_STK_SIZE-1],COLLECT_TASK_PRIO);
OSTaskSuspend(START_TASK_PRIO); //挂起起始任务.
OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
}
void collect_task(void *pdata)
{
while(1) //进行一遍六路热电阻PT100的巡回检测
{
Channelcnt = 1;
while(Channelcnt<7)
{
Switch_ChannelSelect(on, Channelcnt); //选择通道开关
delay_ms(2);
ADS1220_Start ();
while(ADS1220_Dataready);
ADS1220_Dataready = 1;
ADS1220_Get_RTD_Conversion_Data_Calibrated ((unsigned char *)tempData);//得到校准后数据
RTD_code = (((long)tempData[0] << 16) + ((long)tempData[1] << 8) + (long)tempData[2]);
RTD_Temperature = interpolateRTDTemperatureValue (RTD_code);
RTD_float[Channelcnt-1] = RTD_Temperature;
Channelcnt++;
}
for (Channelcnt=1;Channelcnt<7;Channelcnt++)
{
RTD_u16[Channelcnt-1] = RTD_float[Channelcnt-1]*10;
CC2520_PSDU[23+Channelcnt] = RTD_u16[Channelcnt-1]>>8;
CC2520_PSDU[24+Channelcnt] = RTD_u16[Channelcnt-1]&0X00FF;
}
OSMboxPost(msg_collect,RTD_u16); //采集并处理好六路数据后,以消息邮箱的方式传递地址给任务modbus_task
delay_ms(5);
}
}
void modbus_task(void *pdata)
{
u8 err;
while(1)
{
Ctrl_EN = 0; //接受模式
Mbox_u16 = OSMboxPend(msg_collect,0,&err); //请求消息邮箱
ComprehensiveTreatment(); //485串口数据接收发送处理
}
}
void ComprehensiveTreatment(void)
{
u8 i = 0;
u16 CRCdata = 0;
OS_CPU_SR cpu_sr=0; //采用的是方法三来开关中断的,cpu_sr用来存放CPU状态寄存器用的
delay_ms(50);
if( read_done==0 || ReceiveBuf[0]!=0X01 ) return; //接收完成并地址匹配判断
CRCdata = crc16(ReceiveBuf,6);
if(CRCdata != (u16)ReceiveBuf[7]*0x100 + ReceiveBuf[6]) //这是串口助手的写法,如果是Modbus调试精灵,则校验码高位在后,低位前
// if(CRCdata!=((u16)ReceiveBuf[6]*0x100 + ReceiveBuf[7])) //校验成功判断
{
return;
}
switch(ReceiveBuf[1]) //解读功能码
{
case 1:
//Read_Coils();
break;
case 2:
//Read_InputDiscrete();
break;
case 3:
ReadHoldingRegisters();
break;
case 4:
ReadInputRegisters();
break;
case 5:
WriteSingleCoil();
break;
case 6:
WriteSingleRegister();
break;
case 0X10:
WriteDoubleRegister();
break;
default:
TransportError(0x01);
break;
}
Ctrl_EN = 1; // 启动发送
for(i=0;i<RevMaxLength;i++)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //对USART_DR的写操作,将该位清零
USART_SendData(USART1,ReceiveBuf);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)!=SET); //先对USART_SR进行读操作,然后对USART_DR进行写操作可清零该位
}
Ctrl_EN = 0;
for(i=0;i<RevMaxLength;i++)
{
ReceiveBuf = 0;
}
read_done = 0;
}
就好像在紫色代码的地方切换到别的任务一样,而我给紫色代码加上临界段,回数据就一次性回完了,没有卡的现象。望各位大神给予指点啊!
|