写给C8051F330的bootload、WIN32 API iap下载上位机

原创 2013年12月03日 09:03:20

这个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 return cra2            equ 0ah             ; carriage return error_led       equ p1.2           ; active low - clr to turn on load_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 80h main:     clr EA        lcall init          ; init serial port

    clr c     mov c,load_en     jc   done     lcall erase_flash              call  intro         ; print welcome message      call  load1 done:     mov dptr,#prompt8   ; end     lcall outstr              ljmp ram            ; start running program

error:   mov dptr,#prompt6   ; end     lcall outstr stop:   sjmp $

;******************************************************************** ; Receive hex file and write it to flash ;******************************************************************** load1:   lcall inchar skip1:   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 XRAM erase_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-F atoh2:   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 outstr exit:   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,0 prompt2:        db cra1,cra2,'Download Intel hex files to address 1000h',cra1,cra2,0 prompt3:        db cra1,cra2,'*** Cannot decode HEX file.',cra1,cra2,0 prompt4:        db cra1,cra2,'Received OK.',cra1,cra2,0 prompt5:        db cra1,cra2,'Ready to receive hex file..',cra1,cra2,0 prompt6:        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  0x1e00
char 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.0
RICHEDIT_CLASS :Rich Edit version 2.0
SCROLLBAR :滚动条
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.
led	equ 	p1.2

VECTOR	EQU	400H
;================中断向量地址=======================					
			ORG		VECTOR+00H			;复位向量
			LJMP	MAIN
			ORG		VECTOR+03H			;外部中断0 (INT0)
			LJMP	MAIN
			ORG		VECTOR+0BH			;定时器0溢出
			LJMP	MAIN
			ORG		VECTOR+13H			;外部中断1 (INT1)
			LJMP	MAIN
			ORG		VECTOR+1BH			;定时器1溢出
			LJMP	MAIN
			ORG		VECTOR+23H			;UART0
			LJMP	UART_ISR
			ORG		VECTOR+2BH			;定时器2溢出			
			LJMP	MAIN
			ORG		VECTOR+33H			;SPI0
			LJMP	MAIN
			ORG		VECTOR+3BH			;SMB0
			LJMP	MAIN			
			ORG		VECTOR+4BH			;ADC0窗口比较
			LJMP	MAIN
			ORG		VECTOR+53H			;ADC0转换结束
			LJMP	ADC_ISR			
			ORG		VECTOR+5BH			;可编程计数器阵列
			LJMP	MAIN
			ORG		VECTOR+63H			;比较器0
			LJMP	MAIN
			ORG		VECTOR+73H			;定时器3溢出
			LJMP	MAIN			

;================程序入口=======================

			ORG	VECTOR+80H				;程序入口地址
MAIN:
			MOV SP,#30H
			MOV 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:
			mov	r2,#010h		
delay1:			mov	r1,#0ffh
delay:			mov	r0,#0ffh
			djnz	r0,$
			djnz	r1,delay
			djnz	r2,delay1												cpl		led	
			SJMP	MAIN_LOOP

			RET

END


 

 

 这个bootload 做的比较简单,不管怎样这一套东西总算弄齐了,后续再在此基础上完善。

希望做过这方面工作的朋友给些建议,谢谢... O(∩_∩)O~

 

 

 

silicon 官网 C8051F30x bootload 例程

//----------------------------------------------------------------------------- // loader_F30x.c /...
  • momo023
  • momo023
  • 2013年12月03日 09:07
  • 1533

用c8051f330做的VGA显示器红,绿,蓝,信号源软件源代码

用c8051f330做的VGA显示器红,绿,蓝,信号源软件源代码   2010-06-03 16:53:33|  分类: 默认分类|字号 订阅 #include"c...
  • STM32F4
  • STM32F4
  • 2013年10月07日 17:04
  • 2109

一个电路分析(设计经典的单片机采样电阻 C8051F330内部具有10位高精度的A/D转换器)

一个电路分析(转)   即将要分析的电路如下,这个电路本人觉得设计的很经典。这个电路主要完成的任务就是监测流经Q1和采样电阻R6中的电流。单片机C8051F330对电流的...

C8051F330基本外设调试

项目需要用到该系列单片机,根据用户手册,对其外设驱动进行编写。 1.串口配置 这里我使用的波特率是19200,使用内部晶振,波特率调节方法可参照用手册 配置代码如下 void uart...

usb6-usb数据采集仪,sic8051f320下位机,micro2440 linux2.6.32.2上位机

此单片机最多可配置17个ad采集通道,本例用到8个。 usb1.1,full speed 使用两个端点,数据流从sic8051f320的中断输入端点1流向micro2440,输出端点2也配置成中断...

【win32程序控制台】练习题:堆栈数据增删过程的演示(来自c++primer plus p328~330)

/ * 程序的版权和版本声明部分 * Copyright (c) 2012, 华南师范大学软件工程专业 * All rights reserved. * 文件名称:堆栈数据增删过程...
  • Hookc
  • Hookc
  • 2012年04月10日 13:12
  • 782

C8051F340串口IAP

  • 2009年12月09日 10:39
  • 48KB
  • 下载

c8051f330d应用原理图

  • 2008年09月25日 20:57
  • 183KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:写给C8051F330的bootload、WIN32 API iap下载上位机
举报原因:
原因补充:

(最多只允许输入30个字)