好吧,暂时回归嵌入式了,最近搞了Arduino觉得还比较简单,不过这篇blog是讨论task的。因为调试QT的modbus与这个protues仿真的联调通过了。所以还是老老实实爬这个51单片机的程序。
main.cpp:
#include"include/main.h"
#include"include/uart.h"
#include"include/sch.h"
#include"include/modbus.h"
void main()
{
SCH_Init_T0();
uart0_init(9600);
Write_String_To_Buffer("modbus is testing!");
SCH_Add_Task(Uart_Update,0,2,1);
SCH_Start();
while(1)
{
SCH_Dispatch_Tasks();
}
}
main.h
#ifndef _MAIN_H
#define _MAIN_H
//#include
#include
#define OSC_FREQ (11059200UL)
#define OSC_PER_INST (12)
typedef unsigned char U8;
typedef unsigned int U16;
typedef unsigned long LONG;
typedef signed char S8;
#ifndef TRUE
#define FALSE 0
#define TRUE (!FALSE)
#endif
#define RETURN_NORMAL (bit) 0
#define RETURN_ERROR (bit) 1
#define INTERRUPT_Timer_0_Overflow 1
#define INTERRUPT_Timer_1_Overflow 3
//#define INTERRUPT_Timer_2_Overflow 5
#define INTERRUPT_EXTERNAL_0 0
#define INTERRUPT_EXTERNAL_1 2
#define INTERRUPT_UART_Rx_Tx 4
#define INTERRUPT_UART1_Rx_Tx 8
#define ERROR_SCH_TOO_MANY_TASKS (1)
#define ERROR_SCH_CANNOT_DELETE_TASK (2)
extern volatile bit key_update_flag ;
#endif
SCH.h:
#ifndef SCH_H
#define SCH_H
void SCH_Init_T0(void) ;
void SCH_Start(void) ;
void SCH_Report_Status(void);
void SCH_Dispatch_Tasks(void);
U8 SCH_Add_Task(void (code *)(void), U16, U16, bit);
bit SCH_Delete_Task(U8);
typedef idata struct
{
void (code * pTask)(void);
U16 Delay;
U16 Period;
U8 RunMe;
U8 Co_op;
} sTaskH;
#define SCH_MAX_TASKS (4)
#endif
SCH.cpp:
#include"include/main.h"
#include"include/sch.h"
#define TIME_OUT_ERROR 0x78
sTaskH SCH_tasks_G[SCH_MAX_TASKS];
U8 Error_code_G = 0;
static void SCH_Manual_Timer0_Reload(void);
extern bit frame_ok;
extern U8 timeout;
void SCH_Init_T0(void)
{
U8 i;
for (i = 0; i < SCH_MAX_TASKS; i++)
{
SCH_Delete_Task(i);
}
Error_code_G = 0;
TMOD &= 0xF0;
TMOD |= 0x01;
SCH_Manual_Timer0_Reload();
ET0 = 1;
}
void SCH_Start(void)
{
EA = 1;
}
void SCH_Update(void) interrupt INTERRUPT_Timer_0_Overflow
{
U8 Index;
SCH_Manual_Timer0_Reload();
for (Index = 0; Index < SCH_MAX_TASKS; Index++)
{
if (SCH_tasks_G[Index].pTask)
{
if (SCH_tasks_G[Index].Delay == 0)
{
if (SCH_tasks_G[Index].Co_op)
{
SCH_tasks_G[Index].RunMe += 1;
}
else
{
(*SCH_tasks_G[Index].pTask)();
SCH_tasks_G[Index].RunMe = 0;
if (SCH_tasks_G[Index].Period == 0)
{
SCH_tasks_G[Index].pTask = 0;
}
}
if (SCH_tasks_G[Index].Period)
{
SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period;
}
}
else
{
SCH_tasks_G[Index].Delay -= 1;
}
}
}
if(timeout)
{
timeout--;
if(timeout == 0)
{
frame_ok = 1;
}
}
}
//5ms timebase
void SCH_Manual_Timer0_Reload()
{
TR0 = 0;
// TH0 = 0xEE; //5ms
// TL0 = 0x00;
TH0 = 0xf2; //1ms
TL0 = 0x6c;
TR0 = 1;
}
void SCH_Dispatch_Tasks(void)
{
U8 Index;
for (Index = 0; Index < SCH_MAX_TASKS; Index++)
{
if ((SCH_tasks_G[Index].Co_op) && (SCH_tasks_G[Index].RunMe > 0))
{
(*SCH_tasks_G[Index].pTask)();
SCH_tasks_G[Index].RunMe -= 1;
if (SCH_tasks_G[Index].Period == 0)
{
SCH_tasks_G[Index].pTask = 0;
}
}
}
//SCH_Report_Status();
//SCH_Go_To_Sleep();
}
U8 SCH_Add_Task(void (code* Fn_p)(), // Task function pointer
U16 Del, // Num ticks 'til task first runs
U16 Per, // Num ticks between repeat runs
bit Co_op) // Co_op / pre_emp
{
U8 Index = 0;
while ((SCH_tasks_G[Index].pTask != 0) && (Index < SCH_MAX_TASKS))
{
Index++;
}
if (Index == SCH_MAX_TASKS)
{
Error_code_G = ERROR_SCH_TOO_MANY_TASKS;
return SCH_MAX_TASKS;
}
SCH_tasks_G[Index].pTask = Fn_p;
SCH_tasks_G[Index].Delay = Del;
SCH_tasks_G[Index].Period = Per;
SCH_tasks_G[Index].Co_op = Co_op;
SCH_tasks_G[Index].RunMe = 0;
return Index; // return position of task (to allow later deletion)
}
bit SCH_Delete_Task(U8 Task_index)
{
bit Return_code;
if (SCH_tasks_G[Task_index].pTask == 0)
{
Error_code_G = ERROR_SCH_CANNOT_DELETE_TASK;
Return_code = RETURN_ERROR;
}
else
{
Return_code = RETURN_NORMAL;
}
SCH_tasks_G[Task_index].pTask = 0;
SCH_tasks_G[Task_index].Delay = 0;
SCH_tasks_G[Task_index].Period = 0;
SCH_tasks_G[Task_index].RunMe = 0;
return Return_code; // return status
}
/*void SCH_Report_Status(void)
{
#ifdef SCH_REPORT_ERRORS
// ONLY APPLIES IF WE ARE REPORTING ERRORS
// Check for a new error code
if (Error_code_G != Last_error_code_G)
{
// Negative logic on LEDs assumed
Error_port = 255 - Error_code_G;
Last_error_code_G = Error_code_G;
if (Error_code_G != 0)
{
Error_tick_count_G = 60000;
}
else
{
Error_tick_count_G = 0;
}
}
else
{
if (Error_tick_count_G != 0)
{
if (--Error_tick_count_G == 0)
{
Error_code_G = 0; // Reset error code
}
}
}
#endif
}
/*void SCH_Go_To_Sleep()
{
PCON |= 0x01; // Enter idle mode (generic 8051 version)
// Entering idle mode requires TWO consecutive instructions
// on 80c515 / 80c505 - to avoid accidental triggering
//PCON |= 0x01; // Enter idle mode (#1)
//PCON |= 0x20; // Enter idle mode (#2)
}
*/
uart.h:
#ifndef UART_H
#define UART_H
#define RECV_BUFFER_LENGTH 15
#define TRAN_BUFFER_LENGTH 20
typedef idata struct
{
U8 Out_written_index_G;
U8 Out_waiting_index_G;
U8 Tran_buffer[TRAN_BUFFER_LENGTH];
U8 status;
}UART_TRAN;
typedef idata struct
{
U8 In_read_index_G;
U8 In_waiting_index_G;
U8 Recv_buffer[RECV_BUFFER_LENGTH];
U8 status;
}UART_RECV;
typedef union
{
U16 item;
struct
{
U8 high;
U8 low;
}convert;
}CHAR_CONVERT;
void uart0_init(U16 BAUD_RATE);
void Send_Char(U8 CHARACTER);
void Uart_Update();
void Write_Char_To_Buffer(U8 CHARACTER) ;
void Write_String_To_Buffer(U8* STR_PTR);
#endif
uart.cpp:
#include"include/main.h"
#include"include/uart.h"
#include"include/sch.h"
#include"include/modbus.h"
#include
#define ERROR_USART_WRITE_CHAR 0x55
volatile UART_TRAN uart_tran_data;// _at_ 0xc0;
volatile UART_RECV uart_recv_data;// _at_ 0x80;
extern U8 Error_code_G;
bit frame_ok = 0;
U8 timeout;
void uart0_init(U16 BAUD_RATE)
{
PCON &= 0x7F;
SCON = 0x50;
TMOD |= 0x20;
TH1 = (256 - (U8)((((LONG)OSC_FREQ / 100) * 3125)
/ ((LONG) BAUD_RATE * OSC_PER_INST * 1000)));
TL1 = TH1;
TR1 = 1;
ES = 1;
}
void Send_Char(U8 CHARACTER)
{
TI=0;
SBUF=CHARACTER;
while(TI==0);
TI=0;
}
void Uart_Update()
{
if(frame_ok)
{
frame_Parse();
uart_recv_data.In_waiting_index_G = 0;
frame_ok =0;
}
if (uart_tran_data.Out_written_index_G < uart_tran_data.Out_waiting_index_G)
{
Send_Char(uart_tran_data.Tran_buffer[uart_tran_data.Out_written_index_G]);
uart_tran_data.Out_written_index_G++;
}
else
{
uart_tran_data.Out_waiting_index_G = 0;
uart_tran_data.Out_written_index_G = 0;
}
}
void Uart0RxdInterrupt(void) interrupt INTERRUPT_UART_Rx_Tx using 2
{
U8 temp;
if(RI)
{
RI = 0;
temp = SBUF;
// Send_Char(temp);
if(frame_ok==0)
{
if(uart_recv_data.In_waiting_index_G == uart_recv_data.In_read_index_G)
{
uart_recv_data.In_waiting_index_G = 0;
uart_recv_data.In_read_index_G = 0;
}
if(uart_recv_data.In_waiting_index_G
modbus.cpp:
#include"include/main.h"
#include"include/uart.h"
#include"include/modbus.h"
code U8 auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
/* CRCµÍλ×Ö½ÚÖµ±í*/
code U8 auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};
#define LACAL_ADRR 0x01
extern UART_TRAN uart_tran_data;
extern UART_RECV uart_recv_data;
U8 Coil_Status_TBL[5] = {0x55,0x55,0x55,0x55,0x55}; //40¸öÏßȦ £¬·ÖΪ5×é
U8 Switch_Status_TBL[5] = {0x00,0x00,0x00,0x00,0x00};//40¸öÀëÉ¢¿ª¹Ø£¬·ÖΪ5×é
U8 Coil_Output_TBL[5] = {0x00,0x00,0x00,0x00,0x00};
U16 Crc16(U8 *buf, U16 DataLen)
{
U8 uchCRCHi = 0xFF ; /* ¸ßCRC×Ö½Ú³õʼ»¯ */
U8 uchCRCLo = 0xFF ; /* µÍCRC ×Ö½Ú³õʼ»¯ */
U16 uIndex ; /* CRCÑ»·ÖеÄË÷Òý */
while (DataLen--) /* ´«ÊäÏûÏ¢»º³åÇø */
{
uIndex = uchCRCHi ^ *buf++ ; /* ¼ÆËãCRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}
bit frame_Parse()
{
CHAR_CONVERT Crc;
U8 Lacal_Adrr;
U8 Fun_Code;
Crc.item = Make_word(uart_recv_data.Recv_buffer[uart_recv_data.In_waiting_index_G-2],\
uart_recv_data.Recv_buffer[uart_recv_data.In_waiting_index_G-1]);
if(Crc.item != Crc16(uart_recv_data.Recv_buffer,uart_recv_data.In_waiting_index_G-2))
{
return FALSE;
}
Lacal_Adrr = uart_recv_data.Recv_buffer[0];
Fun_Code = uart_recv_data.Recv_buffer[1];
if(Lacal_Adrr != LACAL_ADRR&&Lacal_Adrr!=0)
{
return FALSE;
}
if(Lacal_Adrr == LACAL_ADRR)
{
Write_Char_To_Buffer(LACAL_ADRR);
switch(Fun_Code)
{
case 1:
{
Read_coil_status();
}
break;
case 2:
{
Read_switch_status();
}
break;
case 3:
{
Read_hold_register();
}
break;
case 4:
{
Read_input_register();
}
break;
case 5:
{
force_set_coil();
}
break;
case 6:
{
pre_single_register();
}
break;
case 15:
{
Set_multi_coils();
}
break;
case 16:
{
Pre_set_multi_register();
}
break;
default:
break;
}
}
}
U16 Make_word(U8 a,U8 b)
{
CHAR_CONVERT temp;
temp.convert.high=a;
temp.convert.low=b;
return (temp.item);
}
////////////////////////////////////////////////////////////////////////////////////
void read_coil_status_value()
{
U8 value;
P2 = 0xff;
value = P2;
Coil_Status_TBL[0] = value;
}
void Read_coil_status()
{
U16 address;
U8 count;
U8 coil_status;
U16 temp_crc;
U8 i;
Write_Char_To_Buffer(uart_recv_data.Recv_buffer[1]);
address = (uart_recv_data.Recv_buffer[2]<<8)+uart_recv_data.Recv_buffer[3];
count = (uart_recv_data.Recv_buffer[4]<<8)+uart_recv_data.Recv_buffer[5];
if(count%8 != 0)
{
count = count/8 + 1;
}
else
{
count = count/8;
}
Write_Char_To_Buffer(count);
read_coil_status_value();
for(i = 0;i < count; i++)
{
coil_status = Coil_Status_TBL[address + i];
Write_Char_To_Buffer(coil_status);
}
temp_crc = Crc16(uart_tran_data.Tran_buffer,uart_tran_data.Out_waiting_index_G);
Write_Char_To_Buffer((U8)(temp_crc>>8));
Write_Char_To_Buffer((U8)(temp_crc));
}
/////////////////////////////////////////////////////////////////////////////////
void read_switch_status_value()
{
U8 value;
P2 = 0xff;
value = P1;
Switch_Status_TBL[0] = value;
}
void Read_switch_status()
{
U16 address;
U8 count;
U8 switch_status;
U16 temp_crc;
U8 i;
Write_Char_To_Buffer(uart_recv_data.Recv_buffer[1]);
address = (uart_recv_data.Recv_buffer[2]<<8)+uart_recv_data.Recv_buffer[3];
count = (uart_recv_data.Recv_buffer[4]<<8)+uart_recv_data.Recv_buffer[5];
if(count%8 != 0)
{
count = count/8 + 1;
}
else
{
count = count/8;
}
Write_Char_To_Buffer(count);
read_switch_status_value();
for(i = 0;i < count; i++)
{
switch_status = Switch_Status_TBL[address + i];
Write_Char_To_Buffer(switch_status);
}
temp_crc = Crc16(uart_tran_data.Tran_buffer,uart_tran_data.Out_waiting_index_G);
Write_Char_To_Buffer((U8)(temp_crc>>8));
Write_Char_To_Buffer((U8)(temp_crc));
}
//////////////////////////////////////////////////////////////////////////////////////
void Read_hold_register()
{
}
//////////////////////////////////////////////////////////////////////////////////////
void Read_input_register()
{
}
//////////////////////////////////////////////////////////////////////////////////////
void force_set_coil()
{
}
//////////////////////////////////////////////////////////////////////////////////////
void pre_single_register()
{
}
//////////////////////////////////////////////////////////////////////////////////////
void Set_coil_output_value()
{
//¸ù¾Ý¾ßÌåÓ¦ÓÃÌí¼Ó´úÂë
P0 = Coil_Output_TBL[0];
}
void Set_multi_coils()
{
U16 address;
U8 count;
U16 temp_crc;
U8 i;
Write_Char_To_Buffer(uart_recv_data.Recv_buffer[1]);
Write_Char_To_Buffer(uart_recv_data.Recv_buffer[2]);
Write_Char_To_Buffer(uart_recv_data.Recv_buffer[3]);
address = (uart_recv_data.Recv_buffer[2]<<8)+uart_recv_data.Recv_buffer[3];
count = (uart_recv_data.Recv_buffer[4]<<8)+uart_recv_data.Recv_buffer[5];
if(count%8 != 0)
{
count = count/8 + 1;
}
else
{
count = count/8;
}
Write_Char_To_Buffer(uart_recv_data.Recv_buffer[4]);
Write_Char_To_Buffer(uart_recv_data.Recv_buffer[5]);
for(i = 0;i < count; i++)
{
Coil_Output_TBL[address + i] =uart_recv_data.Recv_buffer[7+i] ;
}
temp_crc = Crc16(uart_tran_data.Tran_buffer,uart_tran_data.Out_waiting_index_G);
Write_Char_To_Buffer((U8)(temp_crc>>8));
Write_Char_To_Buffer((U8)(temp_crc));
Set_coil_output_value();
}
///////////////////////////////////////////////////////////////////////////////////////
void Pre_set_multi_register()
{
}
modbus.h:
#ifndef MODBUS_H
#define MODBUS_H
U16 Crc16(U8 *buf, U16 DataLen);
bit frame_Parse();
U16 Make_word(U8 a,U8 b);
void Read_coil_status();
void Read_switch_status();
void Read_hold_register();
void Read_input_register();
void force_set_coil();
void pre_single_register();
void Set_multi_coils();
void Pre_set_multi_register();
#endif