外部mcu通过调试接口对CC2530进行编程,基本的功能函数如下:
<p>
//--cc2530 Debug commands---
#define CMD_CHIP_ERASE   0x10
#define CMD_WR_CONFIG    0x18
#define CMD_RD_CONFIG    0x20
#define CMD_READ_STATUS  0x30
#define CMD_RESUME       0x48
#define CMD_DEBUG_INSTR  0x50
#define CMD_BURST_WRITE  0x80
#define CMD_GET_CHIP_ID  0x68
//---------------------------

#define LOBYTE(w) ((unsigned char)(w))
#define HIBYTE(w) ((unsigned char)(((unsigned short)(w) >> 8) & 0xFF))

#define FCTL        0x6270
#define FADDRL      0x6271
#define FADDRH      0x6272
#define FWDATA      0x6273

#define DBGDATA     0x6260 //DMA register
#define X_DMAARM    0x70D6   //  DMA Channel Arm   
#define X_DMAREQ    0x70D7
#define X_DMA1CFGL  0x70D2   //  DMA Channel 1-4 Configuration Address Low Byte
#define X_DMA1CFGH  0x70D3   //  DMA Channel 1-4 Configuration Address High Byte

// Buffers
#define ADDR_BUF0        0x0000 // 1K,存放来自调试接口的数据,长度为1K,0x0000--0x03FF
#define ADDR_DMA_DESC    0x0400 // 从0x0400地址开始存放16字节的数据
#define PROG_BLOCK_SIZE  0xFD

// DMA Channels
#define CH_DBG_TO_BUF0   0x02 //使用通道1
#define CH_BUF0_TO_FLASH 0x04 //使用通道2

//--mcu使用的下载接口引脚,可以根据具体的mcu修改----
sbit DcPin = PADBUF^5;
sbit DdPin = PADBUF^3;
sbit ResetPin = PADBUF^1;

sbit DcPinDir  = PADCON1^5;
sbit DdPinDir  = PADCON1^3;
sbit ResetPinDir = PADCON1^1;
//-------------------------------------------------------------------------

void Delayus(unsigned short us)
{
        while(us--)
        {
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
        }
}

/*********************************************************************************
 * Writes a byte on the debug interface. Sets the direction of port 0 at the end.
 * DdPin must be output when this function is called.
 * param:
   num---Byte to write
  dir---Direction of all pins on port 0 that is to be written at the end.
*********************************************************************************/
void cc2530_Write_Debug_Byte(unsigned char num, unsigned char dir)
{
 unsigned char i;
 
 for (i=0; i<8; i++)
 {  
  DdPin = (num&0x80) ? 1 : 0;     
  DcPin = 1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();   
  num <<= 1;       
  DcPin = 0; //在时钟的下降沿把数据输出               
 }
 
 DdPinDir = dir;  
}

/*****************************************************
 * Reads a byte from the debug interface.
 * Requires DdPin to be input when function is called.
 * return:
      Byte read
*****************************************************/
unsigned char cc2530_Read_Debug_Byte(void)
{
 unsigned char i,num;
   
 for (i = 0; i < 8; i++)
 {  
  DcPin = 1; // clock out data  
  num <<= 1;  
  num |= DdPin;  
  DcPin = 0;  
 }
   
 return num;
}

/**********************************************************************************************************************
 * brief Issues a command on the debug interface. Only commands that return one
 * param:
   cmd---Command byte
  input_bytes---Pointer to the array of input bytes
  num_input_bytes---The number of input bytes
 * return Data:
  returned by command
**********************************************************************************************************************/
unsigned char cc2530_Write_Debug_Command(unsigned char cmd, unsigned char *input_bytes, unsigned short num_input_bytes)
{  
 unsigned short i;  
 unsigned char output = 0;  
 unsigned char dir;
       
 dir = (num_input_bytes == 0) ? 0 : 1;//如果没有输入字节,把方向改为输入  
 cc2530_Write_Debug_Byte(cmd, dir);
     
 for(i = 0; i < num_input_bytes; i++)
 {      
  dir = (i == num_input_bytes-1) ? 0 : 1;//在最后一个字节把方向改为输入  
  cc2530_Write_Debug_Byte(input_bytes[i], dir);  
 }
       
 while( DdPin&1 ) //等待cc2530的引脚方向改变完成,拉低此引脚,说明cc2530已经准备好输出数据
 {  
  cc2530_Read_Debug_Byte();  
 }
     
 output = cc2530_Read_Debug_Byte();
 
 //重新配置SDI引脚为输出
 DdPinDir = 1;

return output;
}

/*************************************
* 读取cc2530的ID值
* 参数:
*   buf:输出数据缓存,2个字节
*************************************/
void cc2530_Get_Id(unsigned char *buf)
{
 cc2530_Write_Debug_Byte(CMD_GET_CHIP_ID,0);

while( DdPin&1 ) //等待cc2530的引脚方向改变完成,拉低此引脚,说明cc2530已经准备好输出数据
 {  
  cc2530_Read_Debug_Byte();  
 }
     
 buf[0] = cc2530_Read_Debug_Byte();
 buf[1] = cc2530_Read_Debug_Byte();
}

/*************************************************************************
 * write a byte to the XDATA in the DUP

* param:
 *    address----XDATA address
   values---the bytes to write
 *************************************************************************/
void cc2530_Write_Xdata_Memory(unsigned short address, unsigned char value)
{
 unsigned char instr[3];
 
 instr[0] = 0x90;  
 instr[1] = HIBYTE(address);  
 instr[2] = LOBYTE(address);  
 cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 3, instr, 3); //MOV DPTR,#data16

instr[0] = 0x74; //把立即数送到寄存器A    
 instr[1] = value;    
 cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 2, instr, 2); //MOV A,#data
 
 instr[0] = 0xF0; //把数据从寄存器A写入外部RAM    
 cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 1, instr, 1); //MOVX @DPTR,A
    
}

/**********************************************************************************************************
 * Writes a block of data to the XDATA region in the DUP
 * param:
      address---XDATA start address
      values---Pointer to the array of bytes to write
    num_bytes---Number of bytes to write
***********************************************************************************************************/
void cc2530_Write_Xdata_Memory_Block(unsigned short address, const unsigned char *values, unsigned short num_bytes)
{
 unsigned char instr[3];
 unsigned short i;
 
 instr[0] = 0x90;  
 instr[1] = HIBYTE(address);  
 instr[2] = LOBYTE(address);  
 cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 3, instr, 3); //MOV DPTR,#data16
 
 for (i = 0; i < num_bytes; i++)
 {
  instr[0] = 0x74; //把立即数送到寄存器A    
  instr[1] = values[i];    
  cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 2, instr, 2); //MOV A,#data
  
  instr[0] = 0xF0; //把数据从寄存器A写入外部RAM    
  cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 1, instr, 1); //MOVX @DPTR,A
  
  instr[0] = 0xA3; //增加数据指针    
  cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 1, instr, 1);//INC DPTR
 }
}

/***********************************************************
 * Read a byte from a specific address in XDATA in the DUP

* param:
 *    address----XDATA address

* return Value
 *    read from XDATA
 ***********************************************************/
unsigned char cc2530_Read_Xdata_Memory(unsigned short address)
{
 unsigned char instr[3];

instr[0] = 0x90;  
 instr[1] = HIBYTE(address);  
 instr[2] = LOBYTE(address);  
 cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 3, instr, 3); //MOV DPTR,#data16  
 
 instr[0] = 0xE0; //把外部RAM(16为地址)的值写入寄存器A  
 return cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 1, instr, 1); //MOVX A,@DPTR
}

/************************************************************************************************************
 * 读取cc2530 xdata区的数据
 * 参数:
 *   address:xdata区地址
 *   pOutBuf:输出数据缓存
 *   num_bytes:要读取的数据长度
 * 返回值:
 *   无
 ***********************************************************************************************************/
void cc2530_Read_Xdata_Memory_Block(unsigned short address, unsigned char *pOutBuf, unsigned short num_bytes)
{
 unsigned char instr[3];
 unsigned short i;

instr[0] = 0x90;  
 instr[1] = HIBYTE(address);  
 instr[2] = LOBYTE(address);  
 cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 3, instr, 3); //MOV DPTR,#data16
 
 for( i=0; i<num_bytes; i++ )
 {
  instr[0] = 0xE0; //把外部RAM(16为地址)的值写入寄存器A  
  pOutBuf[i] = cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 1, instr, 1); //MOVX A,@DPTR

instr[0] = 0xA3; //增加数据指针    
  cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 1, instr, 1); //INC DPTR
 }
}

/****************************************************
 * 写cc2530的sfr寄存器
 * 参数:
 *   address:寄存器地址
 *   value:要写入的值
 * 返回值:
 *   无
 ***************************************************/
void cc2530_Write_Sfr(unsigned char address,unsigned char value)
{
 unsigned char instr[3];
     
 instr[0] = 0x75;//移动一个立即数到直接地址,此处即把bank值写入寄存器address
    instr[1] = address;
 instr[2] = value;
 cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 3, instr, 3); //MOV direct,#data
}

/****************************************************
 * 读取cc2530的sfr寄存器
 * 参数:
 *   address:寄存器地址
 * 返回值:
 *   寄存器中的值
 ***************************************************/
unsigned char cc2530_Read_Sfr(unsigned char address)
{
 unsigned char instr[2];
 
 instr[0] = 0xE5;//把寄存器0x9F中的值写入寄存器A
    instr[1] = address;
 return cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 2, instr, 2);//MOV A,direct   
}

/********************************************************************
 * 依次把数据写入到调试接口
 * 参数:
 *   buf:要写入的数据缓存
 *   num_bytes:要写入的数据字节数
 ********************************************************************/
void cc2530_Burst_Write(unsigned char *buf, unsigned char num_bytes)
{
 unsigned char i;
 
 cc2530_Write_Debug_Byte( CMD_BURST_WRITE, 1 );  
 cc2530_Write_Debug_Byte( num_bytes, 1 );
 
 for(i=0; i<num_bytes-1; i++)
 {
  cc2530_Write_Debug_Byte(buf[i], 1); //
 }
 
 cc2530_Write_Debug_Byte(buf[i], 0); // change dir. to input
 
 while( DdPin&1 )
 {
  cc2530_Read_Debug_Byte();
 }
 
 cc2530_Read_Debug_Byte(); // ignore output
 
 //重新配置SDI引脚为输出
 DdPinDir = 1;
}

/******************************************************************************************************************
* 往cc2530的flash中写入数据
* 参数:
*   lAddr:flash中的线性地址
*   buf:写入数据缓存
*   num_bytes:要写入的字节数
* 返回值:
*   无
*******************************************************************************************************************/
void cc2530_Write_Code_Memory(unsigned long lAddr, unsigned char *buf, unsigned char num_bytes)
{    
 unsigned short sAddr;
     unsigned char dma_desc[16] =
 {
  // Debug Interface -> Buffer 0 (Channel 1)  
  HIBYTE(DBGDATA),   // src[15:8]  
  LOBYTE(DBGDATA),   // src[7:0]
  
  HIBYTE(ADDR_BUF0),  // dest[15:8]  
  LOBYTE(ADDR_BUF0),  // dest[7:0]
  
  HIBYTE(PROG_BLOCK_SIZE),  
  LOBYTE(PROG_BLOCK_SIZE),
  
  31,                      // trigger DBG_BW  
  0x11,                    // increment destination
  
  // Buffer 0 -> Flash controller (Channel 2)
  HIBYTE(ADDR_BUF0),   // src[15:8]  
  LOBYTE(ADDR_BUF0),   // src[7:0]
  
  HIBYTE(FWDATA),    // dest[15:8]  
  LOBYTE(FWDATA),    // dest[7:0]
  
  HIBYTE(PROG_BLOCK_SIZE),  
  LOBYTE(PROG_BLOCK_SIZE),
  
  18,                     // trigger FLASH  
  0x42,                  // increment source   
 };//此处只配置了通道1与通道2,通道1把调试接口输入的数据搬移到ADD_BUF0开始的xdata空间,通道2把ADD_BUF0处的数据写入flash
 
 sAddr = (unsigned short)(lAddr>>2);//由于写入flash时是字(4字节)寻址的,用16位地址(64K)访问256k的空间,256K=64*4

dma_desc[5] = dma_desc[13] = num_bytes;
     
 // Write the 2 DMA descriptors  
 cc2530_Write_Xdata_Memory_Block(ADDR_DMA_DESC, dma_desc, 16);// 16 bytes,从0x0400地址开始存放dma_desc数组中的数据
     
 // Set the pointer to the DMA descriptors  
 cc2530_Write_Xdata_Memory(X_DMA1CFGH, HIBYTE(ADDR_DMA_DESC));  
 cc2530_Write_Xdata_Memory(X_DMA1CFGL, LOBYTE(ADDR_DMA_DESC));    
   
 cc2530_Write_Xdata_Memory(FADDRH, HIBYTE(sAddr));//设置flash的地址  
 cc2530_Write_Xdata_Memory(FADDRL, LOBYTE(sAddr));    
         
 cc2530_Write_Xdata_Memory(X_DMAARM, CH_DBG_TO_BUF0);//把数据从调试接口搬移到xdata区  
 cc2530_Burst_Write(buf,num_bytes);    
 
 // wait for write to finish  
 while(cc2530_Read_Xdata_Memory(FCTL) & 0x80);
     
 // start programming current buffer  
 cc2530_Write_Xdata_Memory(X_DMAARM, CH_BUF0_TO_FLASH);  
 cc2530_Write_Xdata_Memory(FCTL, 0x06); //把数据从xdata区写入flash中
     
 // Programming last buffer in progress, wait until done  
 while(cc2530_Read_Xdata_Memory(FCTL) & 0x80);
}

/******************************************************************************************************************
* 读取cc2530flash中的代码
* 参数:
*   sAddr:bank区中的地址值,其中bank0:0x0000--0x7FFF, bank1-bankn:0x8000--0xFFFF
*   bank:对应的bank值
*   pOutBuf:输出数据缓存
*   num_bytes:要读取的字节数
* 返回值:
*   无
* 对应flash中的线性地址(linear address)与bank值和bank中的地址对应的计算公式如下:
* 如果sAddr<0x8000, linear address = sAddr;
* 如果sAddr>=0x8000,linear address = (sAddr&0x7fff) + bank*0x8000
*******************************************************************************************************************/
void cc2530_Read_Code_Memory(unsigned short sAddr, unsigned char bank, unsigned char *pOutBuf, unsigned char num_bytes)

 unsigned char i;
 unsigned char instr[3];
       
    instr[0] = 0x75;//移动一个立即数到直接地址,此处即把bank值写入寄存器0x9F
    instr[1] = 0x9F;
 instr[2] = bank;
 cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 3, instr, 3);

instr[0] = 0x90;  
 instr[1] = HIBYTE(sAddr);  
 instr[2] = LOBYTE(sAddr);  
 cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 3, instr, 3);
 
 for( i=0; i<num_bytes; i++)
 {
  instr[0] = 0xE4; //清寄存器A        
  cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 1, instr, 1);
  
  instr[0] = 0x93; //把数据从外部RAM写入寄存器A    
  pOutBuf[i] = cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 1, instr, 1);
  
  instr[0] = 0xA3; //增加数据指针    
  cc2530_Write_Debug_Command(CMD_DEBUG_INSTR | 1, instr, 1);
 } 
}

//配置下载主控器的编程引脚
void mcu_Init_Debug_Io()
{
 unsigned char debug_config;
 unsigned short X_CLKCONCMD = 0x70C6;
 unsigned short X_CLKCONSTA = 0x709E;

//引脚方向性选择,初始化配置调试接口为输出
 DdPinDir = 1;//0->输入,1->输出
 DcPinDir = 1;
 ResetPinDir = 1;

ResetPin = 1; //初始化复位引脚为高电平
 DcPin = 0; //初始化时钟电平为低电平
 DdPin = 0;
 Delayus(10);   //大约延时24us

//在复位线拉低的情况下,输出两个clk
 ResetPin = 0;
 Delayus(10);

DcPin = 1;
 _nop_();
 _nop_();
 _nop_();
 DcPin = 0;
 _nop_();
 _nop_();
 _nop_();

DcPin = 1;
 _nop_();
 _nop_();
 _nop_();
 DcPin = 0;
 _nop_();
 _nop_();
 _nop_();

Delayus(10);
 ResetPin = 1;

debug_config = 0x22;  
 cc2530_Write_Debug_Command(CMD_WR_CONFIG, &debug_config, 1);
     
 // Switch to 32 Mhz and wait for it to be stable. This is recommended if  
 // 32 MHz crystal is available during programming. If 32 MHz crystal is  
 // not available, comment out these two lines.  
 cc2530_Write_Xdata_Memory(X_CLKCONCMD, 0x80);  
 while(cc2530_Read_Xdata_Memory(X_CLKCONSTA) != 0x80);
}

//主控器通过调试接口擦除cc2530
void mcu_Erase_Cc2530()
{
 cc2530_Write_Debug_Command(CMD_CHIP_ERASE, 0, 0);  
 while(cc2530_Write_Debug_Command(CMD_READ_STATUS, 0, 0) & 0x80);//查询擦除是否完成,擦除完成后最高位清0
}
</p>

cc2530下载程序相关推荐

  1. 利用AVR单片机 专用下载 USBtinyISP对Arduino UNO下载程序

    简 介: 测试了利用USBtinyISP对于Arduino UNO,也就是ATmega系列的单片机下载Bootloader的过程.通过测试可以看到,利用USBtinyISP可以更快的下载ATmega系 ...

  2. 使用单片机对STC8G,8H,8A进行ISP下载程序

    通过第三方程序实现对STC单片机的程序下载,可以方便进行现场的调试和更新.特别是对于设计远程程序更新.无线程序下载与调试等功能有帮助. 本文给出了下载相关的一些程序设计. STC单片机ISP下载协议 ...

  3. Keil uVision5 下载程序 add flash programming algorithm选项缺少需要的下载算法的解决办法

    用Keil5在下载程序,选择下载算法时,可能会出现找不到对应芯片的情况: 这个时候就需要下载安装,Keil的Legacy support for Arm支持包了: http://www2.keil.c ...

  4. 用st-link通过stvp给stm8下载程序的坑

    用的这种st-link 包装上写着,stm32用下面得20pin,stm8用上面的4pin.然后背后有stm8的接线说明. 我接好了线,开发板没有电...测了一下红线和黑线之间电压0.7V... 只好 ...

  5. JLINK通过SW模式下载程序的方法

    JLINK通过SW模式下载程序的方法 1)概述:JLINK有2种调试模式:JTAG和SWD(串行模式).JTAG是常用模式,大家都熟悉:下载文件如图3: 2)使用SW模式,需要(只需要)4根连线,连接 ...

  6. 嵌入式linux如何下载程序,Linux平台的下载程序-嵌入式系统-与非网

    有许多网络文件下载工具可以在Windows平台下很好地工作,如NetAnts."网际快车".TelePro等,还有像WebZip那样功能强大的离线浏览器.这些工具使我们可以在Win ...

  7. IAR J-Link下载程序出现错误提示:Failed to get CPU status after 4 retries Retry?

    情况一:打开IAR的"Project"------->"Options..."------->"J-Link/J-Trace"- ...

  8. Keil MDK在个别电脑上下载程序失败的解决办法

    文章原始地址: http://feotech.com/?p=90 Keil MDK在个别电脑上无法下载程序 Keil MDK下载程序时显示 No Cortex-M SW Device Found (本 ...

  9. 【arduino】arduino ISP下载程序方法,用arduino uno给M5 Module DC MOTOR下载程序

    微信关注 "DLGG创客DIY" 设为"星标",重磅干货,第一时间送达. 今天用arduino uno给M5的Module DC motor下载程序,别的就不多 ...

最新文章

  1. js 动态校验开始结束时间
  2. 生产制造类企业从企业邮箱切换到自建系统的方案
  3. Python如何实现单例模式?其他23中设计模式python如何实现?
  4. Net 分页功能的实现
  5. 程序员是吃青春饭的吗?未来发展前途如何?
  6. Scene Flow场景流halcon算子,持续更新
  7. MySQL使用学习使用,mysql学习--基本使用_MySQL
  8. 机器学习理论知识部分--偏差方差平衡(bias-variance tradeoff)
  9. 定点运算和浮点运算_C2000浮点运算注意事项——CPU和CLA的差异及误差处理技巧...
  10. Spring容器创建流程(4)调用beanFactory后置处理器
  11. c++语言编程,一个电灯两个开关控制,[理学]四川大学计算机学院精品课程_面向对象程序设计C++课件_游洪越_第一章绪论.ppt...
  12. oracle中showTime用法,ant design vue中日期选择框混合时间选择器的用法
  13. 安装Eclipse ADT插件时遇到的一些问题,错误
  14. 卡方分布、T分布和F分布
  15. 【汇总目录】嵌入式系统技术
  16. 金山html编辑器,fresh html
  17. android9最新系统,【5/31更新】Android 9.0系统升级时间的最新情况
  18. google 搜索关键字技巧 google darking
  19. 1500个工作计划总结PPT模板免费下载网址
  20. USB对拷线Linux,USB对拷线设置教程

热门文章

  1. 第一次用unity b站轻松塔防游戏
  2. 高德地图LOCA图例横着展示
  3. 在线公开课 | 在数据爆炸的当下,教你设计一个能实现9个9数据可靠性的存储系统...
  4. 从Spring Cloud到Kubernetes的微服务迁移实践
  5. Instagram高效推广营销策略
  6. 蓝叠模拟器(bluestacks)设置通过fiddler抓包
  7. gif动图怎么制作?怎么把视频做成gif?
  8. 软件测试自学笔记01:入门综述
  9. MatLab建模学习笔记11——云模型在数据处理中的应用
  10. 小程序获取城市行政区号_小程序中通过经纬度如何获取所在省市区名字(腾讯地图JavaScript SDK)...