ymodem协议c语言,STC单片机ISP-Demo-使用Y-Modem协议源码与库函数分享
#define MAIN_Fosc? ? ? ? ? ? ? ? 22118400L? ? ? ? //定義主時鐘
#define Baudrate0? ? ? ? ? ? ? ? 115200UL? ? ? ? //串口0波特率600~115200
#include? ? ? ? "STC15Fxxxx.H"
#include? ? ? ? "ymodem.h"
#define? ? ? ? WDT_Enable? ? ? ? 0? ? ? ? ? ? ? ? ? ? ? ? //1: 允許內部看門狗,? ? ? ? 0: 禁止
#define D_BRT0_1T_8bit? ? ? ? ? ? ? ? (256 - MAIN_Fosc / 32 / Baudrate0)? ? ? ? //計算波特率? ? ? ? 1T??8bit
#define? ? ? ? ISP_ADDRESS? ? ? ? ? ? ? ? 0xE400? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //ISP開始地址, 高地址必須是偶數, 注意要預留ISP空間,本例程留3K
#define? ? ? ? UserflashLenth ? ? ? ? (ISP_ADDRESS-3)? ? ? ? ? ? ? ? //用戶FLASH長度, 保留個字節存放用戶地址程序的跳轉地址
/*************? ? ? ? 本地變量聲明? ? ? ? **************/
typedef? ? ? ? ? ? ? ? void (*pFunction)(void);
pFunction? ? ? ? Jump_To_Application;
u16? ? ? ? ? ? ? ? ? ? ? ? JumpAddress;
u16? ? ? ? ? ? ? ? FileLength;
u16? ? ? ? ? ? ? ? Y_TimeOut,WaitTime;
u8? ? ? ? ? ? ? ? packets_received, session_begin;
u8? ? ? ? ? ? ? ? idata file_name[FILE_NAME_LENGTH];
u8? ? ? ? ? ? ? ? idata file_size[FILE_SIZE_LENGTH];
u8? ? ? ? ? ? ? ? StartCode[3];
u16? ? ? ? ? ? ? ? FlashDestination;
u16? ? ? ? ? ? ? ? RxCnt;
u8? ? ? ? ? ? ? ? HandCnt;
u8? ? ? ? xdata? ? ? ? RxBuff[1024];
u8? ? ? ? idata? ? ? ? RxBuff_10[10];
u32? ? ? ? ? ? ? ? DownCheckSum,FlashCheckSum;
/*************? ? ? ? 本地函數聲明? ? ? ? **************/
u8? ? ? ? ? ? ? ? Hex2Ascii(u8 dat);
u8? ? ? ? ? ? ? ? UART_Download(void);
u16? ? ? ? ? ? ? ? Str2Int(u8 *inputstr);
void? ? ? ? ISP_WriteByte(u16 addr, u8 dat);
void? ? ? ? ISP_EraseSector(u16 addr);
u8? ? ? ? ISP_ReadByte(u16 addr);
//========================================================================
// 函數: void? ? ? ? TX1_write2buff(u8 dat)
// 描述: 串口發送一個字節.
// 參數: dat: 要發送的字節.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void? ? ? ? TX1_write2buff(u8 dat)
{
TI = 0;
SBUF = dat;
while(!TI);
}
//========================================================================
// 函數: void? ? ? ? PrintString1(u8 *p)
// 描述: 串口發送一個字符串.
// 參數: *p: 要發送的字符串指針.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void? ? ? ? PrintString1(u8 *p)
{
for(; *p > 0; p++)? ? ? ? TX1_write2buff(*p);
}
//========================================================================
// 函數: void? ? ? ? Tx_DEC_U16(u16 j)
// 描述: 把一個16位整型數轉成十進制送串口發送.
// 參數: j: 要處理的16位整型數.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void? ? ? ? Tx_DEC_U16(u16 j)
{
u8? ? ? ? i;
u8? ? ? ? tmp[10];
for(i=4; i<5; i--)? ? ? ? tmp[i] = j % 10 + '0',? ? ? ? j = j / 10;
for(i=0; i<4; i++)
{
if(tmp[i] != '0')? ? ? ? break;
tmp[i] = ' ';
}
for(i=0; i<5; i++)? ? ? ? TX1_write2buff(tmp[i]);
}
//========================================================================
// 函數: void? ? ? ? Tx_HEX_U32(u32 j)
// 描述: 把一個32位長整型數轉成十進制送串口發送.
// 參數: j: 要處理的32位整型數.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void? ? ? ? Tx_HEX_U32(u32 j)
{
u8? ? ? ? i,k;
u8? ? ? ? tmp[10];
for(i=8; i>0; i--)
{
k = ((u8)j) & 0x0f;
if(k <= 9)? ? ? ? tmp[i] = k+'0';
else? ? ? ? ? ? ? ? tmp[i] = k-10+'A';
j >>= 4;
}
for(i=1; i<9; i++)? ? ? ? TX1_write2buff(tmp[i]);
}
//========================================================================
// 函數: void? ? ? ? ReturnNameAndLength(void)
// 描述: 返回程序的文件名和長度, 和累加校驗和.
// 參數: none.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void? ? ? ? ReturnNameAndLength(void)
{
u16? ? ? ? i;
PrintString1("================================\r\n File name:? ???");
for(i=0; i
{
if(file_name[i] == 0)? ? ? ? break;
TX1_write2buff(file_name[i]);
}
PrintString1("\r\n File length:? ?");
Tx_DEC_U16(FileLength);
PrintString1(" Bytes\r\n DownChexkSum:??");
Tx_HEX_U32(DownCheckSum);
PrintString1("\r\n ISP Versiom:? ?2013-4-30 by Coody");
PrintString1("\r\n================================\r\n\r\n");
}
//========================================================================
// 函數: void? ? ? ? UART1_RxPackage(void)
// 描述: 串口接收一個數據塊.
// 參數: none.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void? ? ? ? UART1_RxPackage(void)
{
u16? ? ? ? j;? ? ? ? //5ms超時
//? ? ? ? RI = 0;
RxCnt = 0;
for(j = 0;? ? ? ? j < 5000; j++)? ? ? ? //最后收到一個字節5ms后,超時退出
{
if(RI)
{
RI = 0;
if(RxCnt < 1024)? ? ? ? RxBuff[RxCnt] = SBUF;
else
{
RxBuff_10[RxCnt-1024] = SBUF;
}
if(++RxCnt >= 1034)? ? ? ? RxCnt = 1033;
j = 0;? ? ? ? //重新定時5ms
}
}
#if (WDT_Enable > 0)
WDT_reset(D_WDT_SCALE_256);
#endif
}
//========================================================================
// 函數: void? ? ? ? main(void)
// 描述: 主函數.
// 參數: none.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void? ? ? ? main(void)
{
u8? ? ? ? i;
EA = 0;
Timer0_Stop();
Timer1_Stop();
#if (WDT_Enable > 0)
WDT_reset(D_WDT_SCALE_256);
#endif
S1_8bit();
S1_RX_Enable();
S1_BRT_UseTimer1();
Timer1_AsTimer();
Timer1_1T();
Timer1_8bitAutoReload();
Timer1_InterruptDisable();
TH1 = D_BRT0_1T_8bit;
Timer1_Run();
//? ? ? ? PrintString1("\r\n STC ISP Demo\r\n");
while(1)
{
//? ? ? ? TX1_write2buff('A');
HandCnt = 0;
for(WaitTime = 0; WaitTime < 300; WaitTime++)? ? ? ? ? ? ? ? //1.5秒超時
{
UART1_RxPackage();
if((RxCnt == 1) && (RxBuff[0] == 'd'))
{
if(++HandCnt >= 10)
{
i = UART_Download();
WaitTime = 250;
if(i == 1)? ? ? ? ? ? ? ? ? ? ? ? PrintString1("\r\n User abort!\r\n");
else if(i == 2)? ? ? ? ? ? ? ? PrintString1("\r\n PC Cancel!\r\n");
else if(i == 4)? ? ? ? ? ? ? ? PrintString1("\r\n Programming Error!\r\n");
else if(i == 0)
{
PrintString1("\r\n\r\n Programming Completed Successfully!\r\n");
ReturnNameAndLength();
}
}
}
//? ? ? ? else? ? ? ? HandCnt = 0;
}
if(ISP_ReadByte(ISP_ADDRESS-3) == 0x02)
{
SCON = 0;
AUXR = 0;
TMOD = 0;
TL0 = 0;
TH0 = 0;
TH1 = 0;
TL1 = 0;
TCON = 0;
IAP_CMD = 0;
JumpAddress = ISP_ReadByte(ISP_ADDRESS-2);
JumpAddress = (JumpAddress << 8) | ISP_ReadByte(ISP_ADDRESS-1);? ? ? ? //Jump to user application
Jump_To_Application = (pFunction) JumpAddress;
Jump_To_Application();
}
PrintString1(" No AP\r\n");
}
}
//========================================================================
// 函數: u16 Str2Int(u8 *inputstr)
// 描述: 字符串轉整型.
// 參數: *inputstr: 字符串指針.
// 返回: 16位整型數.
// 版本: V1.0, 2013-4-29
//========================================================================
u16 Str2Int(u8 *inputstr)
{
u16? ? ? ? val;
u8? ? ? ? i;
val = 0;
for (i = 0; i < 5; i++)
{
if((inputstr[i] < '0') || (inputstr[i] > '9'))? ? ? ? break;
val = val * 10 + inputstr[i] - '0';
}
return val;
}
//========================================================================
// 函數: void? ? ? ? ISP_WriteByte(u16 addr, u8 dat)
// 描述: 對一個地址寫FLASH一個字節.
// 參數: addr: 16位FLASH地址.
//? ?? ? dat:??要寫入的一字節數據.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void? ? ? ? ISP_WriteByte(u16 addr, u8 dat)
{
IAP_CONTR = ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY);? ? ? ? //使能IAP功能
ISP_WRITE();? ? ? ? ? ? ? ? ? ? ? ? //編程命令
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8;
IAP_DATA??= dat;? ? ? ? ? ? ? ? //將當前數據送IAP數據寄存器
ISP_TRIG();? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //觸發ISP命令
}
//========================================================================
// 函數: u8? ? ? ? ISP_ReadByte(u16 addr)
// 描述: 從一個地址讀FLASH一個字節.
// 參數: addr: 16位FLASH地址.
// 返回: 讀出的一字節數據.
// 版本: V1.0, 2013-4-29
//========================================================================
u8? ? ? ? ISP_ReadByte(u16 addr)
{
IAP_CONTR = ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY);? ? ? ? //使能IAP功能
ISP_READ();? ? ? ? ? ? ? ? ? ? ? ? //編程命令
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8;
ISP_TRIG();? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //觸發ISP命令
return(IAP_DATA);
}
//========================================================================
// 函數: void? ? ? ? ISP_EraseSector(u16 addr)
// 描述: 對FLASH擦除一個扇區.
// 參數: addr: 16位FLASH地址.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void? ? ? ? ISP_EraseSector(u16 addr)
{
IAP_CONTR = ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY);? ? ? ? ? ? ? ? //使能IAP功能
ISP_ERASE();? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //擦除命令
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8;
ISP_TRIG();? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //觸發ISP命令
}
//========================================================================
// 函數: u8? ? ? ? UART_Download(void)
// 描述: 按Ymodem接收文件數據并寫入用戶FLASH.
// 參數: none.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
u8? ? ? ? UART_Download(void)
{
u16? ? ? ? i;
u8? ? ? ? j;
PrintString1("\r\n\r\n Waiting for the file to be sent ... (press 'a' to abort)\r\n");
Y_TimeOut = 0;
packets_received = 0;
session_begin = 0;
WaitTime = 40;
DownCheckSum = 0;
while(WaitTime > 0)
{
if(Y_TimeOut == 0)
{
TX1_write2buff(CRC16);
Y_TimeOut = 300;
if(WaitTime > 0) WaitTime--;
}
while(Y_TimeOut > 0)
{
UART1_RxPackage();
if(RxCnt == 0)? ? ? ? Y_TimeOut--;
else
{
if(RxCnt == 1)
{
if(RxBuff[0] == EOT)
{
TX1_write2buff(ACK);
Y_TimeOut = 40;
}
else if((RxBuff[0] == ABORT1) || (RxBuff[0] == ABORT2))
{
return 1;
}
}
else if(RxCnt <= 5)
{
if((RxBuff[0] == CANCEL) && (RxBuff[1] == CANCEL))
{
return 2;
}
}
else if((RxCnt == 133) || (RxCnt == 1029))
{
if (RxBuff[PACKET_SEQNO_INDEX] != (RxBuff[PACKET_SEQNO_COMP_INDEX] ^ 0xff))
{
TX1_write2buff(NAK);? ? ? ? //錯誤, 請求重發
Y_TimeOut = 300;
}
else
{
WaitTime = 5;
if (packets_received == 0)? ? ? ? //發送序號為0, 為文件名數據包
{
if (RxBuff[PACKET_HEADER] != 0)??//文件名不為空
{
for (i = 0; i < FILE_NAME_LENGTH; i++)? ? ? ? file_name[i] = 0;
for (i = 0; i < FILE_SIZE_LENGTH; i++)? ? ? ? file_size[i] = 0;
j = PACKET_HEADER;
for (i = 0; (i < FILE_NAME_LENGTH) && (RxBuff[j] != 0); i++)
file_name[i] = RxBuff[j++];? ? ? ? ? ? ? ? //保存文件名
for (i=0, j++; (RxBuff[j] != ' ') && (i < FILE_SIZE_LENGTH); i++)
file_size[i] = RxBuff[j++];? ? ? ? //保存文件長度
FileLength = Str2Int(file_size);? ? ? ? //文件長度由字符串轉成十六進制數據
if (FileLength >= UserflashLenth)? ? ? ? //長度過長錯誤
{
TX1_write2buff(CANCEL);? ? ? ? //錯誤返回2個 CA
TX1_write2buff(CANCEL);
return 3;? ? ? ? ? ? ? ? //長度過長
}
StartCode[0] = ISP_ReadByte(0);? ? ? ? //保存ISP跳轉地址
StartCode[1] = ISP_ReadByte(1);
StartCode[2] = ISP_ReadByte(2);
ISP_EraseSector(0);
ISP_WriteByte(0,StartCode[0]);? ? ? ? //回寫ISP跳轉地址
ISP_WriteByte(1,StartCode[1]);
ISP_WriteByte(2,StartCode[2]);
for(i=0x200; i < UserflashLenth; i+=0x200)? ? ? ? //擦除N頁
ISP_EraseSector(i);
TX1_write2buff(ACK);? ? ? ? //擦除完成, 返回應答
Y_TimeOut = 40;
packets_received ++;
session_begin = 1;
FlashDestination = 0;
DownCheckSum = 0;
}
}
else if(session_begin == 1)? ? ? ? //收過文件名
{
if(RxBuff[PACKET_SEQNO_INDEX] == 0)? ? ? ? //全0數據幀
{
ISP_WriteByte(ISP_ADDRESS-3,StartCode[0]);? ? ? ? //全部下載結束,最后寫用戶入口地址
ISP_WriteByte(ISP_ADDRESS-2,StartCode[1]);
ISP_WriteByte(ISP_ADDRESS-1,StartCode[2]);
TX1_write2buff(ACK);
FlashCheckSum??= ISP_ReadByte(ISP_ADDRESS-3);
FlashCheckSum += ISP_ReadByte(ISP_ADDRESS-2);
FlashCheckSum += ISP_ReadByte(ISP_ADDRESS-1);
for(i = 3;? ? ? ? i < FileLength; i++)? ? ? ? FlashCheckSum += ISP_ReadByte(i);? ? ? ? //計算FLASH累加和
if(FlashCheckSum == DownCheckSum)? ? ? ? return 0;? ? ? ? //正確
else
{
ISP_EraseSector(ISP_ADDRESS-0x200);
return 4;? ? ? ? //寫入錯誤
}
}
else? ? ? ? //數據幀
{
for(i=0; i<1024; i++)? ? ? ? RxBuff[i] = RxBuff[i+3];
RxBuff[1021] = RxBuff_10[0];
RxBuff[1022] = RxBuff_10[1];
RxBuff[1023] = RxBuff_10[2];
RxCnt -= 5;
for(i = 0; (i < RxCnt) && (FlashDestination < FileLength); i++)
{
if(FlashDestination == 0)
{
StartCode[0] = RxBuff[0];
StartCode[1] = RxBuff[1];
StartCode[2] = RxBuff[2];
FlashDestination = 3;
i += 3;
DownCheckSum += RxBuff[0]; DownCheckSum += RxBuff[1]; DownCheckSum += RxBuff[2];
}
ISP_WriteByte(FlashDestination,RxBuff[i]);
DownCheckSum += RxBuff[i];
FlashDestination ++;
}
TX1_write2buff(ACK);? ? ? ? //保存完成, 返回應答
Y_TimeOut = 300;
packets_received ++;
}
}
}
}
}
}
}
return 100;? ? ? ? //其他錯誤
}
總結
以上是生活随笔為你收集整理的ymodem协议c语言,STC单片机ISP-Demo-使用Y-Modem协议源码与库函数分享的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言pi的乘法,c语言 根据公式求出π
- 下一篇: 笔算除法 c语言,《两、三位