写给C8051F330的bootload、WIN32 API iap下载上位机
来源:互联网 发布:js 页面后退 编辑:程序博客网 时间:2024/05/18 02:09
这个bootload非常简陋,源码是在silicon 官网例程和在网上找的一个汇编例程的基础上修改的,经过几天的努力实现了基本功能。
程序主体是用汇编写的,因为感觉用C重定位中断向量比较麻烦。发送HEX文件的上位机使用 win32 API 写的,也相当的简单。
用户程序模板测试了串口中断ADC中断,测试过程中未发现问题。
bootload 在芯片上电后会检测P1.3脚,低电平直接跳转至用户程序,若为高电平则调用flash擦除代码,擦除地址400H之后的10页flash空间,然后等待接收HEX文件,程序下载成功后跳转至用户程序。
C8051F330 bootload 源代码:
开发环境:keil
;iap for c8051f330;data:2013-11-29 ;zxx
$INCLUDE(C8051F330.INC) ; Register definition file.
cra1 equ 0dh ; carriage returncra2 equ 0ah ; carriage returnerror_led equ p1.2 ; active low - clr to turn onload_en equ p1.3 ; active low - clr to turn on
ram set 400h ; programs into
;********************************************************************; Interrupt vector table;******************************************************************** org 0 ; System reset RST ljmp main org 3 ; External 0 IE0 ljmp (ram+3) org 0bh ; Timer 0 TF0 ljmp (ram+0bh) org 13h ; External 1 IE1 ljmp (ram+13h) org 1bh ; Timer 1 TF1 ljmp (ram+1bh) org 23h ; Serial port TI or RI ljmp (ram+23h) org 2bh ; Timer 2 TF2 or EXF2 ljmp (ram+2bh) org 33h ljmp (ram+33h) ;spi org 3bh ljmp (ram+3bh) ;smb0 org 4bh ljmp (ram+4bh) ;adc0 windows org 53h ljmp (ram+53h) ;adc0 convert over org 5bh ljmp (ram+5bh) ;pca org 63h ljmp (ram+63h) ;comparator org 73h ljmp (ram+73h) ;timer3 overflow ;********************************************************************; Main program starts here;;******************************************************************** org 80hmain: clr EA lcall init ; init serial port
clr c mov c,load_en jc done lcall erase_flash call intro ; print welcome message call load1done: mov dptr,#prompt8 ; end lcall outstr ljmp ram ; start running program
error: mov dptr,#prompt6 ; end lcall outstrstop: sjmp $
;********************************************************************; Receive hex file and write it to flash;********************************************************************load1: lcall incharskip1: cjne a,#':',load1 ; each record begins with ':' mov r1,#0 ; init checksum to zero
length: lcall gethex ; get byte from serial port mov b,a ; use b as byte counter jz done ; if b = 0 address: lcall gethex ; get address high byte mov dph,a lcall gethex ; get address low byte mov dpl,a
record_type: lcall gethex ; get record type (ignore this) cjne a,#01h,check1 sjmp done ; if record type is 01h hex file reach the end check1: jz load4 ; if record type is zero then perpare to write to flash sjmp error
load4: acall gethex ;get data byte mov PSCTL,#01H ;MOVX writes to FLASH mov FLKEY,#0A5H mov FLKEY,#0F1H movx @dptr,a ; store in FLASH inc dptr mov PSCTL,#00H ; MOVX writes target XRAM dec b ; repeat until count = 0 mov a,b jnz load4
checksum: acall gethex ; get the HEX record checksum field mov a,r1 ; checksum should be zero
jnz error ;if not, stop download
mov dptr,#prompt4 lcall outstr sjmp load1 ; if so, then get next record
;********************************************************************; erase_flash ; ;********************************************************************erase_flash: mov r3,#08h mov dptr,#ram ;MOVX writes target XRAMerase_all: mov PSCTL,#03h ;MOVX erases FLASH mov FLKEY,#0A5h ;FLASH lock and key sequence 1 mov FLKEY,#0F1h; ;FLASH lock and key sequence 2 clr a movx @dptr,a mov PSCTL,#00h mov a,dph add a,#02h mov dph,a djnz r3,erase_all
clr a mov dptr,#prompt7 lcall outstr ret
;********************************************************************; Get two characters from serial port and form a hex byte. ; Also add byte to checksum in r1.;********************************************************************gethex: lcall inchar ; get first character lcall atoh ; convert to hex swap a ; put in upper nibble mov r0,a ; save it lcall inchar ; get second character lcall atoh ; convert to hex orl a,r0 ; or with first nibble mov r2,a ; save byte add a,r1 ; add byte to checksum mov r1,a ; restore checkum in r1 mov a,r2 ; retrieve byte ret
;********************************************************************; Wait until a char is received from the serial port, and return; that char in the accumulator.;********************************************************************inchar: jnb ri0,inchar ; wait until ri is set clr ri0 ; clear interrupt mov a,sbuf0 ; get character ret
;********************************************************************; ASCII to hex - enter with ascii code in acc. (assume hex char 0-F); exit with hex nibble in A.0-A.3;********************************************************************atoh: clr acc.7 ; ensure parity bit is off cjne a,#3ah,next ; ?? this just sets carry bit ??next: jc atoh2 add a,#9 ; no, adjust for range A-Fatoh2: anl a,#0fh ; yes, convert directly ret
;********************************************************************; Print welcome message;********************************************************************intro: mov dptr,#prompt1 lcall outstr mov dptr,#prompt2 lcall outstr mov dptr,#prompt5 lcall outstr ret
;********************************************************************; Wait until tx ready, then send a char out serial port;********************************************************************outchar: nb ti0,outchar ; wait until ti is set clr ti0 ; clear it mov sbuf0,a ; send acc to serial buffer ret
;********************************************************************; Send a null terminated string out serial port;********************************************************************outstr: clr a movc a,@a+dptr ; get character jz exit ; stop if char == null lcall outchar ; else send it inc dptr ; point to next char sjmp outstrexit: ret
;********************************************************************; Init serial port;********************************************************************init: mov OSCICN,#083h mov RSTSRC,#0x04 ;Enable missing clock detector
anl PCA0MD,#0BFh mov PCA0MD,#000h ;disable watchdog
mov CKCON,#08h mov TCON,#040h mov TMOD,#020h mov TH1,#96h ;115200 mov SCON0,#013h ;enable UART ; 8 bit UART mode mov P0MDOUT, #010h mov XBR0, #001h mov XBR1, #040h ret
prompt1: db cra1,cra2,'zxx''s C8051F330 bootloader - 18 NOV 2013',cra1,cra2,0prompt2: db cra1,cra2,'Download Intel hex files to address 1000h',cra1,cra2,0prompt3: db cra1,cra2,'*** Cannot decode HEX file.',cra1,cra2,0prompt4: db cra1,cra2,'Received OK.',cra1,cra2,0prompt5: db cra1,cra2,'Ready to receive hex file..',cra1,cra2,0prompt6: db cra1,cra2,'Error Load!',cra1,cra2,0 prompt7: db cra1,cra2,'Flash erase OK...',cra1,cra2,0 prompt8: db cra1,cra2,'Received end.',cra1,cra2,0
end
hex文件发送:上位机读取hex文件,每间隔20ms 发送一条记录。测试通过。后续要加上上下位机握手,以及校验。上位机源代码:
开发环境:vs2012
#include "stdafx.h"#include "hex_win.h"#include<windows.h>#include<math.h>#include<stdio.h>#include <Commdlg.h>#include <winbase.h>#define MAX_LOADSTRING 100// 全局变量:HINSTANCE hInst; // 当前实例TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名const double dboffset = 0.000001 ;TCHAR str[80]; static HWND hwndSlectPortButton ,hwndPortNum ,hwnlistbox,hwndpath,hwnSlectbutton,hwnDownloadbutton,hwndList;DWORD dwCommEvent;#define ID_LIST 1#define hex_file_size 0x1e00char hex_file_buffer[hex_file_size];DWORD hex_file_real_size;BOOL Read_hex_file_ok;HANDLE hCom; //全局变量,串口句柄char ReadComstr[64];DWORD ReadCount;//读取的字节数//函数声明ATOM MyRegisterClass(HINSTANCE hInstance);BOOL InitInstance(HINSTANCE, int);LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);void Hex_Fiel_Open_Init(void);BOOL Read_Com(void);void Com_handle(void);BYTE hex2char(char *pBuffer);BOOL Read_Com_Synchronous(void);//////////////////////////////////////////////////////////////////int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPTSTR lpCmdLine, _In_ int nCmdShow){ UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); MSG msg; HACCEL hAccelTable; WNDCLASSEX wcex; HWND hWnd; // 初始化全局字符串 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_HEX_WIN, szWindowClass, MAX_LOADSTRING); wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW|CS_CLASSDC; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE( IDC_HEX_WIN)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE( IDC_HEX_WIN); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); RegisterClassEx(&wcex); //注册主窗口 hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,400,200,600,400,NULL, NULL, hInstance, NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE( IDC_HEX_WIN)); //加载快捷键 while (GetMessage(&msg, NULL, 0, 0)) // 主消息循环 { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam;} //设置串口基本参数BOOL SetComm(void){ hCom = CreateFile( "COM1", //COM1口 GENERIC_READ|GENERIC_WRITE, //允许读和写 0, //独占方式 NULL, OPEN_EXISTING, //打开而不是创建 //FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重叠方式 0, // 同步方式 NULL); if(hCom == INVALID_HANDLE_VALUE) { MessageBox( NULL,"打开COM失败!" ,"Error",MB_OK); return FALSE; } SetWindowText(hwndPortNum,"COM1"); MessageBox( NULL,"打开COM成功" ,"ok",MB_OK); SetupComm(hCom,0x2000,0x2000); //输入缓冲区和输出缓冲区的大小都是1024 COMMTIMEOUTS TimeOuts; //设定读超时 TimeOuts.ReadIntervalTimeout = 1000; TimeOuts.ReadTotalTimeoutMultiplier = 500; TimeOuts.ReadTotalTimeoutConstant = 5000; //设定写超时 TimeOuts.WriteTotalTimeoutMultiplier = 500; TimeOuts.WriteTotalTimeoutConstant = 2000; SetCommTimeouts(hCom, &TimeOuts); //设置超时 DCB dcb; GetCommState(hCom, &dcb); dcb.BaudRate = CBR_115200; //波特率 dcb.ByteSize = 8; //每个字节有8位 dcb.Parity = NOPARITY; //无奇偶校验位 dcb.StopBits = ONESTOPBIT ; //一个停止位 dcb.fBinary = TRUE; dcb.fParity = TRUE; SetCommState(hCom, &dcb); PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);//------------------------------------------------------------------------------- DWORD dwStoredFlags; dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING |EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY ; if (!SetCommMask(hCom, dwStoredFlags)) return FALSE;// error setting communications mask//-------------------------------------------------------------------------------// CloseHandle(hCom); // 一定注意在函数退出之前对句柄进行释放。 return TRUE;}// dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING |EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY ;void Com_handle(void){ switch (dwCommEvent) { case EV_RXCHAR: Read_Com(); break; default: break; }}BYTE hex2char(char *pBuffer){ BYTE byte_l,byte; if(*pBuffer=':') pBuffer++; byte=*pBuffer; pBuffer++; byte_l=*pBuffer; pBuffer++; if(byte<0x3a) byte=(byte&0x0F)<<4; else byte=((byte&0x0F)+9)<<4; if(byte_l<0x3a) byte_l=byte_l&0x0F; else byte_l=(byte_l&0x0F)+9; byte+=byte_l; return byte;} BOOL Write_Hex_File(char *pBuffer) { COMSTAT ComStat; DWORD dwErrorFlags; BOOL bWriteStat; BOOL bReadStat; // DWORD NumberOfBytesWritten;// DWORD dwBytesWrite; BYTE record_lenght;//HEX 文件数校验// UINT load_address;// BYTE load_address_l;// BYTE record_type;// BYTE record_data;// BYTE check_sum; char *send_data_pBuffer; DWORD send_data_length; do { if(*pBuffer==':') { send_data_pBuffer=pBuffer; record_lenght=hex2char(pBuffer); send_data_length=1+2+4+2+(record_lenght*2)+2; ClearCommError(hCom,&dwErrorFlags,&ComStat); bWriteStat = WriteFile(hCom, send_data_pBuffer, send_data_length, &send_data_length, NULL); if (!bWriteStat) { MessageBox( NULL,"写串口失败!" ,"Error",MB_OK); return FALSE; } Sleep(20);// delay 20ms // bReadStat= Read_Com_Synchronous(); bReadStat= Read_Com(); if (!bReadStat) { } } pBuffer++; } while (record_lenght!=0); if (!bWriteStat) { MessageBox( NULL,"写串口失败!" ,"Error",MB_OK); return FALSE; } else return TRUE;}/* load_address=hex2char(pBuffer); load_address_l=hex2char(pBuffer); load_address=(load_address<<8)+load_address_l; record_type=hex2char(pBuffer); */////void Read_Hex_File(char* str) //读取HEX文件,转换为十六进制数据,保存到缓存 hex_buffer,长度为 HexBufferSize/*BlpOverlapped OOL ReadFile( HANDLE hFile, //文件的句柄 LPVOID lpBuffer, //用于保存读入数据的一个缓冲区 DWORD nNumberOfBytesToRead, //要读入的字节数 LPDWORD lpNumberOfBytesRead, //指向实际读取字节数的指针 LPOVERLAPPED //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。 //该结构定义了一次异步读取操作。否则,应将这个参数设为NULL );BOOL ReadFile( HANDLE hFile, //文件的句柄 PVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, //指向实际读取字节数的指针 LPOVERLAPPED lpOverlapped );*/BOOL Read_Com_Synchronous(void){ BOOL bReadStat; bReadStat=ReadFile(hCom,ReadComstr,64,&ReadCount,NULL); if(!bReadStat) { MessageBox( NULL,"读串口失败!" ,"Error",MB_OK); return FALSE; } return TRUE;}//异步读串口BOOL Read_Com(void){ char lpInBuffer[1024]; //用于保存读入数据的一个缓冲区 DWORD dwBytesRead=1024; //要读入的字节数 COMSTAT ComStat; DWORD dwErrorFlags; OVERLAPPED m_osRead; //如文件打开时指定了FILE_FLAG_OVERLAPPED,那么必须,用这个参数引用一个特殊的结构。 //该结构定义了一次异步读取操作。否则,应将这个参数设为NULL memset(&m_osRead,0,sizeof(OVERLAPPED)); m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); ClearCommError(hCom,&dwErrorFlags,&ComStat); dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue); if(!dwBytesRead) return FALSE; BOOL bReadStatus; bReadStatus=ReadFile(hCom,lpInBuffer,dwBytesRead,&dwBytesRead,&m_osRead); if(!bReadStatus) //如果ReadFile函数返回FALSE { if(GetLastError()==ERROR_IO_PENDING) //GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作 { WaitForSingleObject(m_osRead.hEvent,2000); //使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟 PurgeComm(hCom, PURGE_TXABORT| PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); //当串口读操作进行完毕后,m_osRead的hEvent事件会变为有信号 return dwBytesRead; } return 0; } PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); return dwBytesRead;}//读取HEX文件并将其转换成HEX格式,存入缓存;void Read_File(char* str) { HANDLE pfile; pfile =CreateFile(str,GENERIC_READ,0,NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);//用这个函数比OpenFile好 if ( pfile == INVALID_HANDLE_VALUE) { // MessageBox( NULL,"打开文件失败" ,"Error",MB_OK); CloseHandle(pfile); // 一定注意在函数退出之前对句柄进行释放。 Read_hex_file_ok=0; return; } DWORD filesize=GetFileSize(pfile,NULL); ReadFile(pfile,hex_file_buffer,filesize,&hex_file_real_size,NULL);//保存hex文件至缓存 Read_hex_file_ok=1;// char* buffer=new char[filesize+1]; // 最后一位为 '/0',C-Style 字符串的结束符。 // DWORD readsize; // ReadFile(pfile,buffer,filesize,&readsize,NULL); // buffer[filesize]=0; MessageBox(NULL,hex_file_buffer,"hex file",MB_OK); // /* BYTE record_lenght;//HEX 文件数校验 BYTE load_address; BYTE record_type; BYTE record_data; BYTE check_sum;*/// delete[] buffer; // 注意是delete[] 而不是 delete CloseHandle(pfile); // 关闭句柄。 }// 函数: void Hex_Fiel_Open(void)//HEX文件打开// lStructSize // 指定这个结构的大小,以字节为单位。 // Windows 95/98和Windows NT 4.0:特意为Windows 95/98或Windows NT 4.0,及带有WINVER和_WIN32_WINNT >= 0x0500编译时, // 为这个成员使用OPENFILENAME_SIZE_VERSION_400。 // Windows 2000及更高版本:这个参数使用sizeof (OPENFILENAME) 。 #define MAX_FILE_FOR_SEL 20 //最大允许选择的文件数 OPENFILENAME ofn = { OPENFILENAME_SIZE_VERSION_400 };//or {sizeof (OPENFILENAME)} TCHAR szPathName[MAX_PATH *MAX_FILE_FOR_SEL]; //获取文件路径//文件选择对话框void Hex_Fiel_Open_Init(void){ ofn.hwndOwner =GetForegroundWindow(); // 打开OR保存文件对话框的父窗口 ofn.lpstrFilter = "hex文件(*.hex)\0*.hex\0All Files(*.*)\0*.*\0\0"; //过滤器 如果为 NULL 不使用过滤器 //具体用法看上面 注意 \0 ofn.nFilterIndex = 1; lstrcpy(szPathName, TEXT("")); ofn.lpstrFile = szPathName; ofn.nMaxFile = sizeof(szPathName); //存放用户选择文件的 路径及文件名 缓冲区 ofn.lpstrTitle = TEXT("选择要下载的hex文件"); //选择文件对话框标题 TCHAR szCurDir[MAX_PATH]; GetCurrentDirectory(sizeof(szCurDir),szCurDir); ofn.lpstrInitialDir=szCurDir; //设置对话框显示的初始目录 // ofn.Flags = OFN_EXPLORER |OFN_ALLOWMULTISELECT| OFN_FILEMUSTEXIST; //如果需要选择多个文件 则必须带有 OFN_ALLOWMULTISELECT标志 ofn.Flags = OFN_EXPLORER;} //// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)//// 目的: 处理主窗口的消息。//// WM_COMMAND - 处理应用程序菜单// WM_PAINT - 绘制主窗口// WM_DESTROY - 发送退出消息并返回//LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: //按钮处理 wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); if(((HWND)lParam ==hwndSlectPortButton) && (HIWORD(wParam) ==BN_CLICKED)) //搜索串口 按钮处理 { SetComm( ); } if(((HWND)lParam ==hwnSlectbutton) && (HIWORD(wParam) ==BN_CLICKED)) //文件选择按钮处理 { Hex_Fiel_Open_Init(); GetOpenFileName(&ofn); SetWindowText(hwndpath,szPathName); Read_File(szPathName) ; } if(((HWND)lParam ==hwnDownloadbutton) && (HIWORD(wParam) ==BN_CLICKED)) //文件选择按钮处理 { if(Read_hex_file_ok) { Write_Hex_File(hex_file_buffer); //Read_hex_file_ok=0; } else MessageBox( NULL,"选择要下载的hex文件" ,NULL,MB_OK); } break; // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT://绘图代码... hdc = BeginPaint(hWnd, &ps); TextOut(hdc,10,10,"串口号 ",6); EndPaint(hWnd, &ps); break;/*BUTTON :按钮COMBOBOX :复合框 EDIT :编辑 LISTBOX :列表 RichEdit :Rich Edit version 1.0RICHEDIT_CLASS :Rich Edit version 2.0SCROLLBAR :滚动条STATIC :静态"\r\n" 来表示一个换行 //创建编辑框“edit”是windows内部定义的编辑框的窗口类名,系统内部定义类名,不须再注册;*/ case WM_CREATE: hwndPortNum= CreateWindow("edit",NULL,WS_CHILD|WS_VISIBLE|WS_BORDER|ES_AUTOHSCROLL,10,40,100,25,hWnd,NULL,NULL,NULL); hwndSlectPortButton = CreateWindow("button","打开串口",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,120,40,100,25,hWnd,NULL,NULL,NULL); hwndpath =CreateWindow("edit",NULL,WS_CHILD|WS_VISIBLE|WS_BORDER|ES_AUTOHSCROLL,10,70,320,25,hWnd,NULL,NULL,NULL); hwnSlectbutton=CreateWindow("button","选择文件",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,340,70,100,25,hWnd,NULL,NULL,NULL); hwnDownloadbutton=CreateWindow("button","下载程序",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,10,105,100,25,hWnd,NULL,NULL,NULL); // hwnlistbox =CreateWindow( "edit", NULL,WS_VISIBLE|WS_CHILD|WS_BORDER|WS_VSCROLL|ES_MULTILINE|ES_WANTRETURN|ES_AUTOHSCROLL|ES_AUTOVSCROLL,10, 140, 570,190 ,hWnd, NULL, NULL, NULL); hwndList = CreateWindow ("listbox", NULL,WS_CHILD | WS_VISIBLE | LBS_STANDARD,10, 140,100,25,hWnd, (HMENU) ID_LIST,(HINSTANCE) GetWindowLong (hWnd, GWL_HINSTANCE),NULL) ; return 0 ; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0;}// “关于”框的消息处理程序。INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){ UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE;}
芯片的中断入口已重定位。
程序模板:
;P1.2口 LED 闪烁$INCLUDE(C8051F330.INC); Register definition file.ledequ p1.2VECTOREQU400H;================中断向量地址=======================ORGVECTOR+00H;复位向量LJMPMAINORGVECTOR+03H;外部中断0 (INT0)LJMPMAINORGVECTOR+0BH;定时器0溢出LJMPMAINORGVECTOR+13H;外部中断1 (INT1)LJMPMAINORGVECTOR+1BH;定时器1溢出LJMPMAINORGVECTOR+23H;UART0LJMPUART_ISRORGVECTOR+2BH;定时器2溢出LJMPMAINORGVECTOR+33H;SPI0LJMPMAINORGVECTOR+3BH;SMB0LJMPMAINORGVECTOR+4BH;ADC0窗口比较LJMPMAINORGVECTOR+53H;ADC0转换结束LJMPADC_ISRORGVECTOR+5BH;可编程计数器阵列LJMPMAINORGVECTOR+63H;比较器0LJMPMAINORGVECTOR+73H;定时器3溢出LJMPMAIN;================程序入口=======================ORGVECTOR+80H;程序入口地址MAIN:MOV SP,#30HMOV PSW,#00H;-----------------------------------------------------MOV OSCICN,#083h MOV RSTSRC,#0x04; ;Enable missing clock detector ANL PCA0MD,#0BFh MOV PCA0MD,#000h;disable watch dog; mov P1MDOUT,#004h mov XBR1, #040h;-----------------------------------------------------MAIN_LOOP:movr2,#010hdelay1:movr1,#0ffhdelay:movr0,#0ffhdjnzr0,$djnzr1,delaydjnzr2,delay1cplledSJMPMAIN_LOOPRETEND
这个bootload 做的比较简单,不管怎样这一套东西总算弄齐了,后续再在此基础上完善。
希望做过这方面工作的朋友给些建议,谢谢... O(∩_∩)O~
- 写给C8051F330的bootload、WIN32 API iap下载上位机
- 基于Ymodem协议的IAP上位机(C#)
- 使用Win32 Internet API的下载文件
- STM32存储器 — <3> STM32实现IAP(上位机和IAP程序设计)
- USB的上位机
- 我的上位机
- Bootload
- bootload
- 上位机Labview8.2下载与安装
- STM32的IAP下载与设置
- java上位机的界面
- 操作系统的bootload开发部分
- 递归下载FTP目录的win32 api实现和php实现
- 上位机
- 上位机
- 上位机
- 上位机
- 上位机
- C#关于虚方法 virtual 和 override 重写 详解
- js脚本搜集
- C语言两种动态分配二维数组方式的讨论
- 排序算法之计数排序
- 二见钟情之UML时序图
- 写给C8051F330的bootload、WIN32 API iap下载上位机
- 关于ping 工具使用的5个实例
- android中sqlite数据库升级方案
- 将note:加到s1中
- 使用ZBar来读取条形码和二维码的方法
- 捉迷藏
- 如何规划人生
- linux terminal 快捷键
- 两个链表的第一个公共结点