本帖最后由 hmd420304805 于 2012-6-30 08:57 编辑
(增加modbus 和组态王 mcgs通讯 :支持01 03 05 06 10 功能码 )
下面的代码为正在机器使用的一段 加速曲线
CPU为 C8051F340 48M的频率 两个定时器控制4个步进电机进行定位(在某一时刻只有2台电机在运动)
晶震频率 = 48.000000;
极限转速 = 350;
周脉冲数 = 2000;
注:驱动方式为 脉冲+ 方向
废话不多说,需要的就读关键代码吧(整个工程代码比较多,1500多行就不上了)。希望对大家有那么一丝帮助,需要帮忙就联系我也行。
unsigned int code WaitTable[]={
0x24AB, 0x3f5e, 0x3068, 0x6216, 0x7E4B, 0x9093, 0x9D78, 0xA6FA, 0xAE63, 0xB44B, // 10
0xB91B, 0xBD28, 0xC093, 0xC387, 0xC61B, 0xC85C, 0xCA5F, 0xCC2B, 0xCDCB, 0xCF42, // 20
0xD098, 0xD1D2, 0xD2F2, 0xD3FE, 0xD4F5, 0xD5DB, 0xD6B2, 0xD779, 0xD835, 0xD8E6, // 30
0xD98E, 0xDA2C, 0xDAC0, 0xDB4E, 0xDBD5, 0xDC54, 0xDCCE, 0xDD41, 0xDDB0, 0xDE1B, // 40
0xDE80, 0xDEE3, 0xDF40, 0xDF9B, 0xDFF1, 0xE044, 0xE094, 0xE0E2, 0xE12D, 0xE176, // 50
0xE1BC, 0xE1FF, 0xE241, 0xE281, 0xE2BE, 0xE2FB, 0xE334, 0xE36C, 0xE3A4, 0xE3D9, // 60
0xE40D, 0xE43F, 0xE470, 0xE4A1, 0xE4D0, 0xE4FD, 0xE52A, 0xE555, 0xE580, 0xE5A9, // 70
0xE5D1, 0xE5F9, 0xE61F, 0xE646, 0xE66B, 0xE68E, 0xE6B3, 0xE6D5, 0xE6F7, 0xE718, // 80
0xE739, 0xE759, 0xE779, 0xE798, 0xE7B6, 0xE7D4, 0xE7F1, 0xE80E, 0xE82A, 0xE846, // 90
0xE861, 0xE87B, 0xE896, 0xE8B0, 0xE8C9, 0xE8E2, 0xE8FB, 0xE913, 0xE92B, 0xE942, // 100
0xE959, 0xE970, 0xE987, 0xE99D, 0xE9B3, 0xE9C8, 0xE9DD, 0xE9F2, 0xEA07, 0xEA1B, // 110
0xEA2F, 0xEA42, 0xEA56, 0xEA69, 0xEA7C, 0xEA8E, 0xEAA1, 0xEAB3, 0xEAC5, 0xEAD7, // 120
0xEAE8, 0xEAF9, 0xEB0B, 0xEB1C, 0xEB2C, 0xEB3C, 0xEB4D, 0xEB5D, 0xEB6D, 0xEB7D, // 130
0xEB8C, 0xEB9C, 0xEBAB, 0xEBBA, 0xEBC8, 0xEBD7, 0xEBE6, 0xEBF4, 0xEC02, 0xEC10, // 140
0xEC1E, 0xEC2C, 0xEC39, 0xEC47, 0xEC54, 0xEC61, 0xEC6F, 0xEC7C, 0xEC88, 0xEC95, // 150
0xECA1, 0xECAE, 0xECBA, 0xECC6, 0xECD2, 0xECDF, 0xECEB, 0xECF6, 0xED02, 0xED0D, // 160
0xED19, 0xED24, 0xED2F, 0xED3A, 0xED45, 0xED50, 0xED5B, 0xED66, 0xED70, 0xED7B, // 170
0xED85, 0xED90, 0xED9A, 0xEDA4, 0xEDAE, 0xEDB8, 0xEDC2, 0xEDCC, 0xEDD6, 0xEDE0, // 180
0xEDE9, 0xEDF3, 0xEDFC, 0xEE06, 0xEE0F, 0xEE18, 0xEE21, 0xEE2B, 0xEE33, 0xEE3C, // 190
0xEE45, 0xEE4E, 0xEE57, 0xEE60, 0xEE68, 0xEE71, 0xEE79, 0xEE82, 0xEE8A, 0xEE93, // 200
0xEE9B, 0xEEA3, 0xEEAB, 0xEEB3, 0xEEBB, 0xEEC3, 0xEECB, 0xEED3, 0xEEDB, 0xEEE3, // 210
0xEEEA, 0xEEF2, 0xEEFA, 0xEF01, 0xEF09, 0xEF10, 0xEF17, 0xEF1F, 0xEF26, 0xEF2E, // 220
0xEF35, 0xEF3C, 0xEF43, 0xEF4A, 0xEF51, 0xEF58, 0xEF5F, 0xEF66, 0xEF6D, 0xEF74, // 230
0xEF7B, 0xEF81, 0xEF88, 0xEF8E, 0xEF95, 0xEF9C, 0xEFA2, 0xEFA9, 0xEFAF, 0xEFB6, // 240
0xEFBC, 0xEFC3, 0xEFC9, 0xEFCF, 0xEFD5, 0xEFDC, 0xEFE2, 0xEFE8, 0xEFEE, 0xEFF4, // 250
0xEFFA
};
//-----------------------------------------------------------------------------
//电机1、3运动初始化 --->使用定时器2
//-----------------------------------------------------------------------------
void T2_init(void)
{
if(TABM) // 如果平台移动
{
if(dir_1) X+=steps1;//进给方向
else X-=steps1; //原点方向
}
if(UDM) // 如果上下钻移动
{
if(dir_3) U+=steps1;//进给方向
else U-=steps1;//原点方向
}
CKCON |=0xf0;
T2_runflag=1;
nsteps1=steps1;
v0_1=1;
l4=0;
t1=v1*7;
if(steps1<2*t1) v1=steps1/2*t1;
TMR2CN =2; //关定时器 复位中断
TMR2RL=WaitTable[0]; //初始速度赋值
TMR2 = TMR2RL;
ET2=1; //中断使能
TMR2CN |= 1<<2; //开定时器
}
//-----------------------------------------------------------------------------
//电机2、4运动初始化 --->使用定时器2
//-----------------------------------------------------------------------------
void T3_init(void)
{
if(TABM1) // 如果平台移动
{
if(dir_2) Y+=steps2; //进给方向
else Y-=steps2; //原点方向
}
if(UDM1) // 如果上下钻移动
{
if(dir_4) D+=steps2;//进给方向
else D-=steps2; //原点方向
}
CKCON |=0xf0;
T3_runflag=1;
nsteps2=steps2;
l3=0;
v0_2=1;
t2=v2*7;
if(steps2<2*t2) v2=steps2/2*t2;
TMR3CN =2; //关定时器 复位中断 系统时钟
TMR3RL =WaitTable[0]; //初始速度赋值
TMR3 = TMR3RL;
EIE1|=1<<7; //中断使能
TMR3CN |= 1<<2; //开定时器
}
void Timer2_ISR (void) interrupt 5
{
TMR2CN &= ~1<<7; //清中断标志 关定时器
if(T2_runflag)
{
if(UDM)PLU3=!PLU3;
if(TABM)PLU1=!PLU1;
if(l1==0) TMR2RL=WaitTable[l3];
if(steps1-nsteps1<t1) {if(l1<7) l1++;else {l1=0;if(l3<v1)l3++;}}
if(nsteps1<t1) {if(l1<7) l1++;else {l1=0;if(l3>v0_1)l3--;}}
nsteps1--;
if(nsteps1>0) TMR2CN |= 1<<2; //开定时器
if(nsteps1==0)
T2_runflag=0;
if(UDM)PLU3=!PLU3; // if(P4&b6)
if(TABM)PLU1=!PLU1; //if(!P3^3) 限位
}
}
void Timer3_ISR (void) interrupt 14
{
TMR3CN &= ~1<<7; //清中断标志 关定时器
if(T3_runflag)
{
if(UDM1)PLU4=!PLU4; //到限位开关停止发脉冲
if(TABM1)PLU2=!PLU2;
if(l2==0) TMR3RL=WaitTable[l4];
if(steps2-nsteps2<t2) {if(l2<7) l2++;else {l2=0;if(l4<v2)l4++;}}
if(nsteps2<t2) {if(l2<7) l2++;else {l2=0;if(l4>v0_2)l4--;}}
nsteps2--;
if(nsteps2>0) TMR3CN |= 1<<2; //开定时器
if(nsteps2==0)
T3_runflag=0;
if(UDM1)PLU4=!PLU4; //一个中断发一个完整个脉冲段 到限位开关停止发脉冲
if(TABM1) PLU2=!PLU2;
}
}
modbus 协议
uchar Rdata_size= 0;
uchar UART_Input_First = 0;
uchar UART_Output_First = 0;
bit TX_Ready =1;
bit modbus_flag=0;
/* CRC低位字节值表*/
const uchar code 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
} ;
const uchar code 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计算器
//------------------------------
uint crc16(uchar *puchMsg, uint usDataLen)
{
uchar uchCRCHi = 0xFF ; /* 高CRC字节初始化 */
uchar uchCRCLo = 0xFF ; /* 低CRC 字节初始化 */
uint uIndex ; /* CRC循环中的索引 */
while (usDataLen--) /* 传输消息缓冲区 */
{
uIndex = uchCRCHi ^ *puchMsg++ ; /* 计算CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}
//------------------------------
// 定时器0器初始化
//------------------------------
void Timer0_Init(void)
{
TH0 = Overflagtime&0xff00;
TL0 = Overflagtime&0x00ff;
TMOD |= 0x01; // Timer0 in 16-bit reload mode
//CKCON |= 0x02; // Timer0 uses a 1:48 prescaler
ET0=1; // Timer0 interrupt enabled
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
// P0.4 digital push-pull UART TX
// P0.5 digital open-drain UART RX
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
TH1 =0x30;
CKCON &= 0xf0; // SCA1:0 = xx;T1M = 1;
CKCON |= 0x08; //T1M = 1;
TMOD &=0x0f; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
IP |= 0x10; // Make UART high priority
ES0 = 1;
TX_Ready = 1; // Flag showing that UART can transmit
Timer0_Init();
}
/*************************************/
/* 函数名:void modbus_proc(void)
/*功能:modbus 处理函数 每次把整个循环BUFFER都扫描一遍
/* 传入值 void
/*************************************/
void modbus_proc(void)
{
uint crcv;
uchar addr,temp,readCount;
if(modbus_flag)
{
switch(R_Buffer0[1]) //功能码分解
{
case 0x01: //读内部线圈
crcv=crc16(&R_Buffer0[0],6); //求CRC 如果CRC校验不正确则不处理
if(R_Buffer0[6]!=crcv>>8|R_Buffer0[7]!=crcv&0xff) return;
addr=R_Buffer0[3]; //获取起始地址 (不同于寄存器)
readCount =R_Buffer0[5]; //获取读取线圈个数
S_Buffer0[0]=m_addr;
S_Buffer0[2]=0x01;
if(readCount>8) S_Buffer0[2]=2; else S_Buffer0[2]=1;
crcv=reg>>addr;
if(readCount>8)
{
S_Buffer0[3]=2;
S_Buffer0[5]=crcv&0xff;
temp=0xff;
temp=temp<<readCount-8;
temp=~temp;
crcv=crcv>>8;
crcv=temp&crcv;
S_Buffer0[4]=crcv&0xff;
crcv=crc16(&S_Buffer0[0],5);
S_Buffer0[5]=crcv>>8;
S_Buffer0[6]=crcv&0xff;
while(!TX_Ready);
urat0_Send_data(7);
}
else
{
S_Buffer0[3]=1;
temp=0xff;
temp=temp<<readCount;
temp=~temp;
crcv=crcv&temp;
S_Buffer0[4]=crcv&0xff;
crcv=crc16(&S_Buffer0[0],4);
S_Buffer0[4]=crcv>>8;
S_Buffer0[5]=crcv&0xff;
while(!TX_Ready);
urat0_Send_data(6);
}
modbus_flag=0;
break;
case 0x05: //置某个位
crcv=crc16(&R_Buffer0[0],6); //求CRC 如果CRC校验不正确则不处理
if(R_Buffer0[6]!=crcv>>8|R_Buffer0[7]!=crcv&0xff) return;
addr=R_Buffer0[3]; //获取起始地址 (不同于寄存器)
temp=R_Buffer0[4]; //要设置的状态
if(temp==0xff) //置1
{
crcv=1;
crcv=crcv<<addr;
reg=reg|crcv;
}
else //置0
{
crcv=1;
crcv=crcv<<addr;
crcv=~crcv;
reg=reg&crcv;
}
S_Buffer0[0]=m_addr;
S_Buffer0[1]=0x05;
S_Buffer0[2]=0;
S_Buffer0[3]=addr;
S_Buffer0[4]=R_Buffer0[4];
S_Buffer0[5]=R_Buffer0[5];
S_Buffer0[6]=R_Buffer0[6];
S_Buffer0[7]=R_Buffer0[7];
while(!TX_Ready);
urat0_Send_data(8);
modbus_flag=0;
break;
case 0x03: //主机要读本机的寄存器
crcv=crc16(&R_Buffer0[0],6); //求CRC
if(R_Buffer0[6]!=crcv>>8|R_Buffer0[7]!=crcv&0xff) return;
addr=R_Buffer0[3]; //要读的地址 0~6
readCount =R_Buffer0[5]*2; //要读的个数 (16位)
if(addr>50|readCount>100-2*addr) return;
S_Buffer0[0]=m_addr; //目标机地址
S_Buffer0[1]=3; //命令号
S_Buffer0[2]=readCount; //返回字节个数
for(temp=0;temp<readCount+1;temp++)
S_Buffer0[temp+3]=DATA[temp+addr*2]; //数据
crcv=crc16(&S_Buffer0[0],readCount+3); //求CRC
S_Buffer0[readCount+3]=crcv>>8;
S_Buffer0[readCount+4]=crcv&0xff;
while(!TX_Ready);
urat0_Send_data(readCount+5);
modbus_flag=0;
break; //读寄存器
case 0x6: //主机要写本机的寄存器(单个)
addr=R_Buffer0[3]; //要写的地址
DATA[2*addr]=R_Buffer0[4]; //要写数据 高
DATA[2*addr+1]=R_Buffer0[5]; //低
for(temp=0;temp<6;temp++)
S_Buffer0[temp]=R_Buffer0[temp];
crcv=crc16(&S_Buffer0[0],6);
S_Buffer0[6]=crcv>>8;
S_Buffer0[7]=crcv&0xff;
while(!TX_Ready);
urat0_Send_data(8);
modbus_flag=0;
break; //设置单个寄存器
case 0x10: //主机要写本机的寄存器(多个)
addr=R_Buffer0[3]; //要写的地址 0~6
readCount =R_Buffer0[5]*2; //要写的个数 (16位)
if(addr>50|readCount>100-2*addr) return;
for(temp=0;temp<readCount+1;temp++) DATA[addr+temp]=R_Buffer0[6+temp]; //数据copy
S_Buffer0[0]=m_addr;
S_Buffer0[1]=0x10;
S_Buffer0[2]=0x00;
S_Buffer0[3]=addr;
S_Buffer0[4]=0x00;
S_Buffer0[5]=R_Buffer0[5];
crcv=crc16(&S_Buffer0[0],6);
S_Buffer0[6]=crcv>>8;
S_Buffer0[7]=crcv&0xff;
while(!TX_Ready);
urat0_Send_data(8);
modbus_flag=0;
break;//设置多个寄存器
default:break;
}
}
}
// timer0中断处理(modbus一个包接收完成)
// 完成标志为3.5个BYTE的延时时间
//-----------------------------
void Timer0_ISR (void) interrupt 1
{
TR0=0; // Timer0 OFF
if(UART_Input_First<4) //丢数据
{
TH0 = Overflagtime&0xff00; // Init Timer0 High register
TL0 = Overflagtime&0x00ff; // Set the intial Timer0 value
UART_Input_First=0;
return;
}
TR0=0;
if(R_Buffer0[0]==m_addr) //是否是本机地址 并且是已处理完成包
modbus_flag=1;
UART_Input_First = 0; //接收缓冲偏移归零
TH0 = Overflagtime&0xff00; // Init Timer0 High register
TL0 = Overflagtime&0x00ff; // Set the intial Timer0 value
TR0=1; //开定时器
}
//-----------------------------------------------------------------------------
// UART0_Interrupt
//-----------------------------------------------------------------------------
// 串口中断处理
//-----------------------------------------------------------------------------
void UART0_Interrupt (void) interrupt INTERRUPT_UART0
{
uchar Byte;
if (RI0 == 1)
{
RI0 = 0;
Byte = SBUF0; // Read a character from UART
R_Buffer0[UART_Input_First] = Byte;
UART_Input_First++;
TR0 = 0; // Timer0 OFF 说明:modbus的包尾为3.5个Byte的延时
TH0 = Overflagtime>>8; // Init Timer0 High register 使用定时器检查,如果定时器溢出
TL0 = Overflagtime&0xff; // Set the intial Timer0 value 就去处理这个包。
TR0 = 1; // Timer0 On
}
if (TI0 == 1) // Check if transmit flag is set
{
TI0 = 0; // Clear interrupt flag
if (Rdata_size!= 1) // If buffer not empty
{
Byte =S_Buffer0[UART_Output_First];
SBUF0 = Byte; // Transmit to Hyperterminal
UART_Output_First++; // Update counter
Rdata_size--; // Decrease array size
}
else
{
Rdata_size = 0; // Set the array size to 0
TX_Ready = 1; // Indicate transmission complete
}
}
}
//------------------------------
//写串口
//------------------------------
void urat0_Send_data(uchar len)
{
UART_Output_First=0;
Rdata_size=len+1;
while(!TX_Ready);
TX_Ready=0;
SBUF0=S_Buffer0[UART_Output_First];
UART_Output_First++;
Rdata_size--;
}
/*
//------------------------------
//阻塞方式读串口 ( 等待READTIMEOUT个周期)
//传入:需要获取的数据长度
//返回:0 读len个BYTE成功 或返回实际读取个数
//------------------------------
int urat0_Recv_data(uchar len)
{
uchar temp=0;
for(;temp<BUFFERSIZE;temp++) R_Buffer0[temp]=0;
UART_Input_First=0;
temp=0;
while(UART_Input_First<len) {temp++; if(temp>READTIMEOUT) return UART_Input_First;};
return 0;
} */
//-------------------------------------------
//------------EOF------------------
//--------------------------------------------
/*
掉电数据存储
开辟一个CONST数组
用于数据的存储
*/
#include <main.h>
uchar code flash_page[512]; //开辟一个 512 BYTE 的空间
/***********************************/
/* 函数名:void flash_read(void)
/*功能:把FLASH里的数据写进XRAM 在开机时候会启用
/* 传入值
/*返回值
/***********************************/
void flash_read(void)
{
uint temp=0;
while(temp<100)
{
DATA[temp]=flash_page[temp];
temp++;
}
}
/***********************************/
/* 函数名:void flash_write(void)
/*功能:把XRAM里的数据写进FLASH 在掉电的时候会启用
/*工作机制 在掉电的一瞬间 全部外设的供电失效
/*IO输入io口在100ms 以内 全都为 “0”信号
/*但是单片机在储能电容的供电下仍然会运行大致500MS
/*利用这剩余的400 ms的时间进行数据的保存
/***********************************/
void flash_write(void)
{
uint temp=0;
uchar xdata * data p;
bit EA_s=EA;
EA=0;
FLSCL=0x81; //使能FLASH单稳态定时器 SYSCLK =48M
VDM0CN=0x80;//使能VDD监视器
RSTSRC=0X02; //上电复位VDD监视器复位标志
p=(uchar xdata *)&flash_page[0];
FLKEY=0XA5; //关键码1
FLKEY=0XF1; //关键码2
PSCTL |=0X03; //允许擦写
VDM0CN=0x80;//使能VDD监视器
RSTSRC=0X02; //上电复位VDD监视器复位标志
*p=0;
PSCTL &=~0X03; //禁止擦写
temp=0;
PSCTL =0;
PSCTL=0X01; //写使能
p=(uchar xdata *)&flash_page[0];
while(temp<100)
{
FLKEY=0XA5; //关键码1
FLKEY=0XF1; //关键码2
*p=DATA[temp];
p++;
temp++;
}
PSCTL =0; //清除写使能
EA=EA_s;
} |