fish001

  • 2020-08-12
  • 发表了主题帖: MSP430编程器仿真器以及JTAG、SBW、BSL接口的区别

    对于51系统来说,很容易理解编程器和仿真器。 通俗的说,仿真器是用来调试仿真的,编程器是用来批量生产时对MCU进行烧写目标代码的。 对于MSP430来说,无论仿真还是烧写程序一般可以通过:JTAG、SBW、BSL接口进行。JTAG、SBW接口可以用于仿真接口,BSL接口不能用于仿真。而编程器则三种接口都支持。 所以并不能说JTAG只支持仿真不支持编程,这是概念错误,JTAG仅仅是一种接口协议而已。 下面简单描述一下三种接口的区别: 1、JTAG是边界扫描技术,其在430内部有逻辑接口给JTAG使用,内部有若干个寄存器连接到了430的内部数据地址总线上,所以可以用JTAG访问430内部的所有资源,包括对FLASH的读写操作。所以可以用于对MSP430的仿真及编程。主要连接线有TMS、TCK、TDI、TDO、RST、TEST。 2、SBW是SPY-BI-WIRE,可以简称两线制JTAG,主要用SBWTCK(连接到JTAG仿真器的7脚TCK)与SBWTDIO(连接到JTAG仿真器的1脚TDO/TDI),该接口主要用于小于28脚的2系列的430单片机,因为28脚以内的2系列单片机的JTAG接口一般与IO口复用,为了给用户预留更多的IO口,才推出了SBW接口。同样SBW接口可以用于仿真器及编程器。 3、 BSL是TI在对MSP430出厂时预先固化到MCU内部的一段代码,有点类似于DSP的bootloader,但又与bootloader有明显的区别,BSL只能用于对MCU内部的FLASH访问,不能对其他的资源访问,所以只能用作编程器接口。BSL通过UART协议与编程器连接通信。编程器可以发送不同的通信命令来对MCU的存储器做不同的操作。BSL的启动有些特殊,一般430复位启动时PC指针指向FFFE复位向量,但可以通过特殊的启动方式可以使MCU在启动是让PC指向BSL内部固化的程序。启动方式一般是由RST引脚与TEST(或TCK)引脚做一个稍复杂的启动逻辑后产生。BSL启动后,就可以对MCU进行访问了。 一般的MCU都有代码加密功能,430是如何实现的呢?外部对430内部的代码读写只能通过上述的三种方式,所以又引入了熔丝位,熔丝位只存在于JTAG、SBW接口逻辑内。BSL内部没有熔丝。当熔丝烧断时(物理破坏,且不可恢复)JTAG与SBW的访问将被禁止,此时只有BSL可以访问。而通过BSL对MCU的访问是需要32个字节的密码,该密码就是用户代码的中断向量表。所以430的加密系统到目前为止尚无被解密的报告。 仿真器的型号一般有UIF(USB接口,支持JTAG、SBW)、PIF(并口,只支持JTAG)、EZ430(USB接口的,只支持SBW模式) 专业编程器有GANG430(串口、一拖8个,支持JTAG、SBW,不支持BSL);多功能编程器(JTAG、SBW、BSL)。这些编程器都可以做离线烧写,即脱离计算机来对目标板烧写。 也可以用仿真器配专业的软件来做编程器,这类软件有MSPFET、FET-PRO430等。

  • 发表了主题帖: MSP430单片机调试接口和JTAG仿真器原理图

    SP430单片机调试接口简介 MSP430F1、F2、F4系列产品中,采用的是4线JTAG接口。也即TMS(模式选择)、TCK(JTAG时钟信号)、TDO(数据输出)、TDI(数据输入)。 在4线制的JTAG接口中,TI公司有定义一个常规的14pin接口方式   而在MSP430F2系列产品中,包含了两种JATG接口界面,一种是上述所说的4线制JTAG。另一种是MSP430F20xx系列产品中名为“Spy Bi-Wire”的调试接口,此接口方式采用是2线制。分别为SBWTCK(时钟)、SBWTDO(数据线),加上GND、VCC两引脚此接口只需4根引线。目前支持2线制接口的仿真器有TI eZSP430 USB接口仿真器。

  • 发表了主题帖: MSP430的AD采集程序

    /* 基于msp430f169/149的双通道AD采集程序,,内部2.5V参考电压,中断处理方式,采用滑动平均的滤波 方式,在测试时稳定的电压的采集中在小数点后两位保持不动。 */ #include "ADC.h" #include "stdio.h" #include #define ADC_BUF_LEN   200 uint16_t ADC_Buf0[ADC_BUF_LEN] = {0} ; //ADC数据缓冲 uint16_t ADC_Buf1[ADC_BUF_LEN] = {0} ; uint32_t ADC_Buf0_Sum = 0 ; uint32_t ADC_Buf1_Sum = 0 ; void ADC_Init(void) {     P6SEL|=(BIT0 + BIT1);                                    //选择ADC通道          ADC12CTL0 &= ~ENC ;                              //ADC12CTL0寄存器部分重要的位需要bit1 == 0 才能修改     ADC12CTL0 |= ADC12ON + SHT0_15 + REF2_5V + REFON + ADC12OVIE + ADC12TOVIE ; //ADC电源控制开,16个CLK,内部基准2.5V     //ADC12CTL1|= ADC12SSEL1 +  ADC12SSEL1 + ADC12DIV_1;            //SMCLK做时钟源     ADC12CTL1 = SHP + CONSEQ_3 ;          ADC12MCTL0 = INCH_0 + SREF_1;                       //p60,参考电压内部2.5     ADC12MCTL1 = INCH_1 + SREF_1 +  EOS ;               //p61,参考电压内部2.5V     //ADC12MCTL2 = INCH_10 + SREF_1 + EOS;                //内部温度传感器     ADC12IE |= BIT0 + BIT1 ;                                  //中断允许 } /*启动ADC转换*/ void ADC_Start(void) {    ADC12CTL0 |= ADC12SC + ENC ;     } /*ADC 中断服务函数*/ #pragma vector=ADC12_VECTOR __interrupt void ADC12ISR (void) {          /*使用滑动平均值滤波*/     uint16_t res ;     float vol ;     static uint8_t index = 0 ;     uint8_t i ;          ADC12CTL0 &= ~ENC ;     ADC12CTL0 &= ~ADC12SC ;     ADC12CTL0 &= ~(BIT0+BIT1) ;     ADC12IE &= ~(BIT0|BIT1) ;                                  //关中断     //while((ADC12CTL1&0x01)==1);  //如果ADC忙,则等待,否则读取ADC转换数值          i = index % ADC_BUF_LEN ;          res = ADC12MEM0 ;             //转移通道0的AD数据     ADC_Buf0_Sum -= ADC_Buf0[i] ; //最后一个数组空间放数组的和     ADC_Buf0[i] = res & 0x0FFF ;     ADC_Buf0_Sum += ADC_Buf0[i] ; //将新的数据与总和相加     res = ADC_Buf0_Sum / ADC_BUF_LEN ;     vol = 1.0 * res * 2.5 / 4095 ;     //vol = vol * 1.2184 ;               //开发板的参数     vol = vol * 0.9954324 ;               //我的实验板          //printf("%u\t%f\t\t",res,vot) ;                         res = ADC12MEM1 ;             //转移通道1的AD数据     ADC_Buf1_Sum -= ADC_Buf1[i] ; //最后一个数组空间放数组的和     ADC_Buf1[i] = res & 0x0FFF ;     ADC_Buf1_Sum += ADC_Buf1[i] ; //将新的数据与总和相加     res = ADC_Buf1_Sum / ADC_BUF_LEN ;     vol = 1.0 * res * 2.5 / 4095 ;     //vol = vol * 1.2184 ;        //开发板的参数     vol = vol * 0.9954324 ;        //我的实验板         index++ ;     ADC12IE |= BIT0 + BIT1 ;                                  //中断允许     ADC12CTL0 |= (BIT0+BIT1) ;     ADC_Start() ;      }

  • 发表了主题帖: MSP430F5529 ADC参考

    1.ADC12_A初始化参数 typedef struct ADC_MemMap {   union   {     uint16_t CTL0;     struct     {       uint16_t SC             :1;  /* ADC12 Start Conversion */       uint16_t ENC            :1;  /* ADC12 Enable Conversion */       uint16_t TOVIE          :1;  /* ADC12 Timer Overflow interrupt enable */       uint16_t OVIE           :1;  /* ADC12 Overflow interrupt enable */       uint16_t ON             :1;  /* ADC12 On/enable */       uint16_t ADCREFON       :1;  /* ADC12 Reference on */       uint16_t REF2_5V        :1;  /* ADC12 Ref 0:1.5V / 1:2.5V */       uint16_t MSC            :1;  /* ADC12 Multiple SampleConversion */       uint16_t SHT0           :4;  /* ADC12 Sample Hold 0 Select  */       uint16_t SHT1           :4;  /* ADC12 Sample Hold 1 Select  */     };   };   union   {     uint16_t CTL1;     struct     {       uint16_t ADBUSY         :1;    /* ADC12 Busy */       uint16_t CONSEQ         :2;    /* ADC12 Conversion Sequence Select  */       uint16_t SSEL           :2;    /* ADC12 Clock Source Select  */       uint16_t DIV            :3;    /* ADC12 Clock Divider Select  */       uint16_t ISSH           :1;    /* ADC12 Invert Sample Hold Signal */       uint16_t SHP            :1;    /* ADC12 Sample/Hold Pulse Mode */       uint16_t SHS            :2;    /* ADC12 Sample/Hold Source  */       uint16_t CSTARTADD      :4;    /* ADC12 Conversion Start Address  */     };   };   union   {     uint16_t CTL2;     struct     {       uint16_t REFBURST       :1;    /* ADC12+ Reference Burst */       uint16_t ADCREFOUT      :1;    /* ADC12+ Reference Out */       uint16_t SR             :1;    /* ADC12+ Sampling Rate */       uint16_t DF             :1;    /* ADC12+ Data Format */       uint16_t RES            :2;    /* ADC12+ Resolution  */       uint16_t TCOFF          :1;    /* ADC12+ Temperature Sensor Off */       uint16_t PDIV           :1;    /* ADC12+ predivider 0:/1   1:/4 */     };   };   uint16_t RESERVED_1[2];   uint16_t IFG;   uint16_t IE;   uint16_t IV;   struct   {       uint8_t INCH            :4;     /* ADC12 Input Channel Select*/       uint8_t REF             :3;     /* ADC12 Select Reference  */       uint8_t EOS             :1;     /* ADC12 End of Sequence */   }MCTL[16];   uint16_t MEM[16]; }volatile * ADC_MemMapPtr; #define ADC12_SSEL_ADC12OSC       0 #define ADC12_SSEL_ACLK           1                    #define ADC12_SSEL_MCLK           2 #define ADC12_SSEL_SMCLK          3    #define ADC12_SREF_0            0 #define ADC12_SREF_1            1 #define ADC12_SREF_2            2 #define ADC12_SREF_3            3 #define ADC12_SREF_4            4 #define ADC12_SREF_5            5 #define ADC12_SREF_6            6 #define ADC12_SREF_7            7 #define ADC_BASE_PTR                     ((ADC_MemMapPtr)__MSP430_BASEADDRESS_ADC12_PLUS__) 1.2 参考电压 typedef enum {   ADC_VREF_1_5V         ,  //内部1.5V   ADC_VREF_2_5V         ,  //内部2.5V   ADC_VREF_3_3V         ,  //供电电压作为参考电压   ADC_VREF_External     ,  //使用外部提供参考电压 }ADC_VREF;         //参考电压 值得注意的是,参考手册里面解释如下 3 单片机的采样电压是不允许超过参考电压: Nadc=4095∗Vin−VR−VR+−VR− 从参考公式来看,必须小于参考电压,如果超过参考电压,输出只能到最大参考电压,并且还会可能烧坏单片机。 1.3 转换精度 typedef enum {   ADC_8bit              ,  //8 位精度,最大值256-1   ADC_10bit             ,  //10位精度,最大值1024-1   ADC_12bit             ,  //12位精度,最大值4096-1 }ADC_Resolution;   //精度 2 初始化 /******************************************************************************* *  函数名称:ADC_Init(uint16_t ch,ADC_VREF Vref,ADC_Resolution nBit) *  功能说明:ADC初始化一个或多个ADC通道 *  参数说明:             uint16_t ch     :要初始化的通道             ADCVREF Vref    :参考电压             ADC_Resolution nBit   :转换精度 *  函数返回:无 ********************************************************************************/ void ADC_Init(uint16_t ch,ADC_VREF Vref,ADC_Resolution nBit) {   ADC12->ENC = DISABLE; //先对该位复位,否则置位后有些寄存器不能再进行操作   uint16_t SREF_RegValue = 0u;   switch(Vref)           //选择参考电压   {   case ADC_VREF_1_5V:     REFCTL0 &=~ REFMSTR;                //把REF参考电压控制权交给ADC     ADC12->ADCREFON = BIT_SET;     ADC12->REF2_5V = RESET;     SREF_RegValue = ADC12_SREF_1;       //使用内部提供的参考电压     break;   case ADC_VREF_2_5V:     REFCTL0 &=~ REFMSTR;     ADC12->ADCREFON = BIT_SET;     ADC12->REF2_5V = BIT_SET;     SREF_RegValue = ADC12_SREF_1;       //使用内部提供的参考电压     break;   case ADC_VREF_External:           P5SEL |= BIT0;       //VeREF+     P5SEL |= BIT1;       //VeREF-     SREF_RegValue = ADC12_SREF_2;       //使用外部参考电压   case ADC_VREF_3_3V:     SREF_RegValue = ADC12_SREF_0;       //使用电源电压作为参考电压,     break;   default :break;   }   //初始化通道   uint16_t CH_Mask = 0x01;   for(uint8_t CH_Num=0; CH_Num < ADC_CH_NUM; CH_Num++)   {     if(ch & CH_Mask)   //要初始化的通道     {       if((CH_Mask & InitialedChannel_Bit) == 0)   //如果该通道未被初始化过                      {         ADC12->MCTL[InitialedChannel_Num].INCH = CH_Num;         ADC12->MCTL[InitialedChannel_Num].REF  = SREF_RegValue;//参考电压选择,通道设置         ADC_Channel_Bit[InitialedChannel_Num] = CH_Mask;//将该通道初始化标志置位                                                 InitialedChannel_Bit |= CH_Mask; //置位已初始化的通道标志位         InitialedChannel_Num ++;//初始化的通道数加1       }       else //如果是之前已经初始化过的通道,则要在这里从新设置一下,只设置通道参考电压       {         ADC12->MCTL[ADC_GetChanelNum((ADC_CHn)CH_Mask)].REF = SREF_RegValue;//改变参考电压                   }     }     CH_Mask <<= 1;   }   if(InitialedChannel_Num > 1)                 //有多个通道时要加上序列通道结束位   {     for(int i=0; i<(InitialedChannel_Num-1); i++)   //前面所有通道序列结束位清零     {       ADC12->MCTL.EOS = RESET;     }     ADC12->MCTL[InitialedChannel_Num-1].EOS = BIT_SET;  //最后一通道加上序列通道转换结束位   }   //一般配置   ADC12->SHT0 = M0_M7_SAMPLE_HOLD_TIME; //0-7通道采样与保持时间   ADC12->SHT1 = M8_M15_SAMPLE_HOLD_TIME;//8-15通道采样与保持时间   ADC12->ON = BIT_SET;/ 采样时间,AD内核开启   ADC12->MSC = BIT_SET;   ADC12->SSEL = ADC12_SSEL_ADC12OSC;//时钟选择   ADC12->SHP = BIT_SET;   //有多个通道时设为序列通道单次转换模式,单个通道时设为单通道单次转换模式      ADC12->CONSEQ = (InitialedChannel_Num > 1) ? BIT_SET : RESET;           //设置ADC精度   ADC12->RES = nBit;       //开启时钟   UCS->MODOSC_REQEN = BIT_SET; //ADC使用的是MODCLK 所以在这里配置该时钟,约5MHz左右   //配置通道为第二功能   if(ch & 0x00ff)   {      GPIO_MultiBits_Init(P6,(ch & 0x00ff),GPI | SEL);   }   if(ch & 0xf000)   {      GPIO_MultiBits_Init(P7,((ch & 0xf000)>>12),GPI | SEL);   }   if(ch & ADC_CH10) //如果使用了温度传感器通道,则开启温度传感器   {     ADC12->TCOFF = RESET;   }   ADC12->ENC = ENABLE;     //该位必须在初始化完成后再置位   //DELAY_MS(5);     //延时等待参考电压建立 } 这里采样与保持间隔 //宏定义ADC12MEM8 to ADC12MEM15采样与保持时间  0-15 #define M8_M15_SAMPLE_HOLD_TIME  3 //宏定义ADC12MEM0 to ADC12MEM7 采样与保持时间  0-15 #define M0_M7_SAMPLE_HOLD_TIME   3 注意点 1. 初始化后所有通道精度相同,即所有通道转换精度只取决于最后一次配置的精度 2. 所有通道内部参考电压只能使用1.5或2.5V中的一种 使用示例: ADC_Init(ADC_CH1+ADC_CH3,ADC_VREF_1_5V,ADC_10bit);         //同时初始化两个通道,使用内部提供的1.5V参考电压,10位精度 3.采样实例 /*! *     COPYRIGHT NOTICE *     Copyright (c) 2016,CTGU-GB *     All rights reserved. * * * @file       main.c * @brief       MSP430F5529 平台主程序 * @author     CTGU-GB * @version     v2.7 * @date        2016-11-26 */ #include "include.h" double adcDataTest[20]; /******************************************************************************* *  函数名称:ADC_Filter(u32 num,double *adcDataStorage) *  功能说明:ADC滤波函数 *  作者:klaus 邮箱:xcf2016a@outlook.com *  参数说明:uint8_t num 输入滤波数据个数 *            double *adcDataStorage:滤波数组 *  函数返回:滤波结果 ********************************************************************************/ double ADC_Filter(uint8_t num,double *adcDataStorage) {   uint8_t i,j,k;   uint8_t noswap=1;   double adc_sum_tmp=0,adc_ave_tmp=0;   for(i=0;i<num-1;++i){          for(j=0;j<num-i-1;++j)       {           if(adcDataStorage[j]>adcDataStorage[j+1]){               adcDataStorage[j]=adcDataStorage[j]+adcDataStorage[j+1];               adcDataStorage[j+1]=adcDataStorage[j]-adcDataStorage[j+1];               adcDataStorage[j]=adcDataStorage[j]-adcDataStorage[j+1];               noswap=0;           }        }       if(noswap) break;   }   for(k=2;k<num-2;k++)adc_sum_tmp += adcDataStorage[k];   //adc_sum_tmp -= (adcDataStorage[0]+adcDataStorage[1]+adcDataStorage[num-2]+adcDataStorage[num-1]);       adc_ave_tmp=adc_sum_tmp/(num-4);   adc_sum_tmp=0;   return adc_ave_tmp; } void main() {   DisableInterrupts();          //禁止总中断   LED_Init(LED_ALL);              //LED灯初始化   OLED_Init();   ADC_Init(ADC_CH2,ADC_VREF_3_3V,ADC_10bit);       //初始化通道,P6.1   while(1)   {       int i;     for(i=0;i<20;i++)     {       adcDataTest=ADC_ReadChanelOnce(ADC_CH2)*3.3/1023;       DELAY_MS(10);     }     double ad = ADC_Filter(20,adcDataTest);     OLED_PrintfAt(FONT_ASCII_8X16,0,0,"ADValue:\n%.3f V",ad);         //在指定位置打印   } }

  • 发表了主题帖: MSP430 ADC模数例程

    下面以路灯控制器的设计为例说明 ADC12 的使用方法。路灯在一定的亮度值以上将熄灭,而在亮度低于某个数值时亮起来。下面是简图。当亮度较大、光线较强时,光敏电阻的电阻值比较小,这时它与下面 10K 分压,则送达 ADC12 的电压比较高;而当亮度较小、光线较弱时,光敏电阻的电阻值比较大,这时它与下面 10K 分压,则送达 ADC12 的电压比较低。通过 ADC12 模块转换出具体的表示光强度的数值(光线越强,转换后的数值越大,但不成正比例),再设定一个开启路灯的阀值数据,则可以通过实际测量的光强度数据与阀值数据 比较得到是否开启路灯的目的。 下面是具体示例程序:(使用单通道单次定时转换)。 #include "msp430x44x.h" //使用 MSP430F447 void main(void) { WDTCTL = WDTPW+WDTHOLD; // 停止看门狗 P6SEL |= 0x01; //定义 P6.0 为模拟输入通道 0 ADC12CTL0 = ADC12ON+SHT0_2; // 打开 ADC12 电源,并设置采样时间 ADC12CTL1 = SHP; ADC12CTL0 |= ENC; //使能转换 while (1) { delay(60000) //延时 1 秒(大致,相当于定时器的作用) ADC12CTL0 |= ADC12SC; // 开始启动转换 while ((ADC12IFG & ADC12BUSY)==0); //等待转换的完成 if(ADC12MEM0<1234) //读取转换结果并比较以得到结论 P1OUT |= BIT0; //当亮度低于阀值时打开路灯 else P1OUT ^= BIT0; //当亮度高于或等于阀值时关闭路灯 } }

  • 发表了主题帖: msp430g2553初学到设计经验分享

    MSP430g2553是16位MCU,供电电压可以低至1.8V,并包含如下图中的外设,并有多种低功耗模式可供开发者灵活使用。   MSP430G2553,个人觉着:低功耗是其最大亮点。为此可谓是处心积虑。因而中断/低功耗模式在430的应用中便显得千娇百媚,楚楚动人! msp430g2553例程,msp430g2553初学到设计经验分享   MSP430G2x13和MSP430G2x53系列是超低功耗混合信号微控制器,具有内置的16位定时器、多达24个支持触摸感测的I/O引脚、一个多用途模拟比较器以及采用通用串行通信接口的内置通信能力。   MSP430G2553应用非常广泛,这里,先跟大伙看下这个中断的情况。   #include《msp430g2553.h》   #include “in430.h”   int main(void)   {   WDTCTL = WDTPW + WDTHOLD; //禁止看门狗计数   P1DIR=BIT0+BIT1;//P1.0\1设置为输出,P1.4/5是输入   P1OUT=BIT0+BIT1+BIT4+BIT5;//P1.0\1为高,P.4/5上拉   P1REN=BIT4+BIT5;//P1.4上拉使能   P1IE=BIT4+BIT5;//P1.4开中断   P1IES=BIT4+BIT5;//中断沿选择   __enable_interrupt();//开总中断   while(1);//没事做   }   #pragma vector=PORT1_VECTOR   __interrupt void PORT1()//P1口中断服务程序   {   unsigned int i=0;   unsigned char PushKey=0;   PushKey=P1IFG&(BIT4+BIT5);//读取是哪个键按下   for(i=0;i《65535;i++);//延时后再作判断,避免是抖动   if(!(P1IN&PushKey))//没有按下,则为抖动,标志清零   P1IFG=0;   if((P1IN&PushKey))//判断是否有键按下   {   for(i=0;i《65535;i++);   if((P1IN&PushKey))   {   if((PushKey&BIT4))   P1OUT^=BIT0;   if((PushKey&BIT5))   P1OUT^=BIT1;   }   P1IFG&=~(BIT4+BIT5);   }   }   这个程序,最出彩的地方在于“while(1);”这个等待的语句。   中断没发生前,程序在停这儿等待,就相当于CPU一直停在儿没事做歇着,也许是在等待戈多。一旦中断条件发生,在这里是按键,它便好像逮着什么似的,便进入中断,去执行中断程序中的代码。   这里,我们可见。中断没来之前,CPU它无所事事,却没有关闭,仍在耗电。中断来了之后,它赶忙地处理中断程序。前前后后,他总在折腾。肯定累得够戗。 msp430g2553例程,msp430g2553初学到设计经验分享  

  • 2020-08-09
  • 发表了主题帖: 使用MSP430™MCU智能模拟组合设计电流环路

            温度,压力,流量,pH值–这些是在过程控制和工厂自动化应用中通常监视的一些变量。气动系统最初控制和监视这些变量,直到1950年代,当时电子产品变得更加便宜且足够坚固,可以实施。电子技术的发展为过程控制应用创建了新的控制和监视标准:4至20mA电流环路。 一般功能包括使用传感器监视环境变量(例如温度,气体,光线或其他条件),并将其转换为4至20 mA的电流环路。 (如果您不熟悉电流环路,您可能会想知道“为什么使用电流而不是电压?”使用电流而不是电压来量化传感器的测量有几个优点。环境传感器的数据通常在过程控制中以长距离发送在将长电缆引入系统中时,可能会出现电压降;但是,使用电流而非电压时,信号降级的风险大大降低,电流对噪声的敏感性也比电压低,这对于降低噪声非常重要。有电机的工厂环境。)         图1显示了一般的电流环路设计。监视环境状况的传感器会将数据输入到模数转换器(ADC)中。该ADC将传感器数据转换为数字数据,并将其馈送到微控制器(MCU)进行处理。处理完数据后,MCU会将数字数据发送到数模转换器(DAC)。然后,DAC将使用其模拟输出和晶体管来控制电流环路中的电流水平。 图1:通用4至20mA电流环路变送器设计 这些电流环路设计需要多个组件。在印刷电路板(PCB)上安装传感器,ADC,MCU,DAC和电源电路会迅速消耗电路板空间并增加物料清单(BOM)成本。 该MSP430FR2355可以帮助在不牺牲性能,为电流回路设计一个集成的解决方案减轻这些负担。智能模拟组合是MSP430FR2355的新外设,提供了四个可配置的模拟模块。每个模块包括一个12位DAC和一个具有可编程增益放大器功能的运算放大器(op amp)。 使用Smart Analog Combo外设时,可以采用图1所示的常规电流环路设计,并将其简化为图2所示的配置。如果需要,此配置还可以实现隔离。 图2:采用MSP430FR2355智能模拟组合外设的4至20mA电流环路变送器设计 在DAC配置中配置SAC外设最终会导致更多的电路板空间和更少的BOM成本。图3显示了Smart Analog Combo中的功能DAC配置。 图3:Smart Analog Combo电流环路配置 第一个智能模拟组合模块(SAC3)采用DAC配置。该模块根据DAC输出产生电压。第一块的输出连接到第二块(SAC1)的正输入,后者是在通用模式下配置的运算放大器。SAC1模块控制晶体管的栅极电压。电流值I Loop取决于外部电阻值和SAC3中DAC的输出电压。有关此设计的更多信息,请参见带有MSP430智能模拟组合的4至20mA环路供电RTD温度变送器参考设计。 根据您系统的要求,可以使用MSP430FR2355的内部12位ADC 进一步集成电流环变送器设计(并使BOM成本最小化)。图4显示了这种集成。 图4:具有内部ADC的Smart Analog Combo电流环路配置变送器 除了智能模拟组合以外,MSP430FR2355 MCU还采用小型RSM封装,符合最高105°C的温度要求。此包措施的4x4mm并且比大的QFN,6x6mm的小近60%MSP430FR2355 RHA包(图5)。对于可能存在尺寸限制的工厂或过程控制应用,采用集成了模拟芯片的高密度32引脚封装进行传感会非常有益。 图5:32引脚RSM封装与40引脚RHA封装的尺寸比较(mm) 该MSP430FR2355提供的节省电路板空间和降低BOM成本的好处-同时提供可靠的性能。电流环路发送器是可以从MSP430FR2355的附加值中受益的众多系统之一。

  • 发表了主题帖: 使用毫微功耗运算放大器实现电流感应

         设计者通过将一个非常小的“分流”电阻串联在负载上,在两者之间设置一个电流感应放大器或运算放大器,实现用于系统保护和监测的电流感应。虽然专用的电流感应放大器能够发挥十分出色的电流感应作用,但如果特别注重功耗的情况下,精密的毫微功耗运算放大器则是理想的选择。   有两个位置可以根据负载放置分流电阻:负载与电源之间,或者负载与接地之间。   在这两种情况下,为了利用已知阻值的电阻来感应电流,通过运算放大器来测量分流电阻两端的电压。运用欧姆定律(公式1),可以确定电流消耗:   其中 V 表示电压,I 表示电流,R 表示电阻。   选择分流电阻和运算放大器-HC1400P03,这样它们对电路的性能影响最小。 在选择电阻时,根据以下两个条件选用低值电阻:   尽量将电阻两端的压降保持在低水平,使负载的负极在低侧感应时尽可能靠近接地,或者在高侧感应时尽可能靠近电源。   保持低功耗。从公式2可以看出,由于你要测量的是电流,因此它是一个自变量,所以电阻应尽可能小:   这里要说明一点:由于你要测量电流而不是让电流最小化(如我再第一部分中所做的),所以你必须将电阻值最小化,才能让功耗最小化—这与DC增益配置中功耗管理的思路相反。   超低功耗电流测量技术广泛应用于移动电源、手机等终端设备的电池充电和监测,也可以用于保证工业物联网应用的正常运行。   那么在选择电阻值时,可以压到多低呢?简单地说,电阻两端的压降应当大于你所用运算放大器的偏移电压。   示例   假设你要进行低侧差动电流测量,以确保系统中不存在短路和开路。为了简易起见,本示例选用简单的数字,忽略诸如电阻容差之类的参数 电源电压为3.3V。在正确操作的情况下,系统得出最大电流值为10mA;你不想要有效接地,使负载高于100V。你首先要明白一点,分流电阻的压降(由于电流)必须小于或等于100V。   如果你使用公式3来确定最大分流电阻:   则有效接地为100V,如公式4所示:   您必须选用运算放大器,它能够检测到这种压降的变化,表明是否存在故障。由于系统处于正常工作状态时,负载电流在其典型值±10%范围内。当电流变化至少10%时,运算放大器就可以检测出感应电阻两端的电压变化。   如果存在故障(如:开路,低电流导致的欠压,高电流导致的短路或掉电),公式5表示电流的变化(IΔ):   公式6计算出VSHUNT压降的变化:   在这个例子中,我会选择LPV821零漂移毫微功耗放大器。其零漂移技术可实现仅10?V的最大偏移电压,从而检测到故障情况。零漂移运算放大器是高精度(<100V)测量的理想选择。此外,LPV821也是一种毫微功耗放大器,你可以让它一直处于开启状态,持续准确地感测电流,对系统功率预算的影响很小。   感谢阅读“如何以毫微功耗运算放大器实现精密测量”系列的第二部分。我们希望这一系列文章能够为你提供一些关于在直流增益和低侧电流传感应用中使用毫微功耗零漂移运算放大器的益处的见解。

  • 2020-08-08
  • 发表了主题帖: TMS320F28335的IO控制定时计操作

    IO设置   2.1设置功能   GPXMUX1/2:功能选择寄存器     GPXMUX1/2    每组 IO 一般有 32 个 IO 口可以配置。GPXMUX1 对应每组的低 16 个 IO 口,GPXMUX2 对应高 16 个 IO 口 。   这里设置的是GPIO34   所以在 GPBMUX1中    所以向  GPBMUX1 的bit5:4  写入0设置为普通IO。(默认设置 )   2.2:设置IO方向   方向控制寄存器 GPXDIR:如果对应的位为 1 则配置为输出,否则则配置为输入。     代码如下:    EALLOW; GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0; GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; EDIS;   关于  EALLOW、EDIS说明:   DSP由于在上电复位之后,状态寄存器基本上都是清零,而这样的状态下正是上述特殊寄存器禁止改写的状态。为了能够对这些特殊寄存器进行初始化,所以在对上述特殊寄存器进行改写之前,一定要执行汇编指令asm(“EALLOW”)或者宏定义EALLOW来设置状态寄存器1的C6位,在设置完寄存器之后,一定要注意执行汇编指令asm(“EDIS”)或者宏定义EDIS来清除状态寄存器1的C6位,来防止杂散代码或指针破坏寄存器内容。   到此关于GPIO的配置就完成了。 3.控制IO输出电平   置位寄存器:置位寄存器 GPXSET:如果对应的位为 1 则将对应的 IO 口拉高(输出高电平)。     GpioDataRegs.GPBSET.bit.GPIO34 = 1;//设置PGIO34 输出高电平   清零寄存器:强制拉低管脚 GPXCLEAR:如果对应的位为 1 则将对应的 IO 口拉低(输出低电平)。 GpioDataRegs.GPBCLEAR.bit.GPIO34 = 1;//设置GPIO34输出高平   输出翻转寄存器:输出状态翻转寄存器 GPXTOGGLE:如果 GPXTOGGLE 的某位为 1 则将相应的 IO 口输出状态进行翻转。                                                                GpioDataRegs.GPBTOGGLE.bit.GPIO34= 1;//设置PGIO34输出翻转电平 使用定时器实现闪烁LED    1.定时器设置     关于定时器的设置  主要是设置CPUTIMER_VARS  结构体中的参数:      struct CPUTIMER_VARS { volatile struct CPUTIMER_REGS *RegsAddr;//定时器 相关寄存器 Uint32 InterruptCount; //用作定时器中断次数统计 float CPUFreqInMHz; //存放频率 单位MHZ float PeriodInUSec; //中断的计数值 ,到了产生中断。 }; struct CPUTIMER_REGS { union TIM_GROUP TIM; // Timer counter register 定时器计数寄存器 union PRD_GROUP PRD; // Period register 定时器周期寄存器 union TCR_REG TCR; // Timer control register 定时器控制寄存器 Uint16 rsvd1; // reserved 保留 union TPR_REG TPR; // Timer pre-scale low union TPRH_REG TPRH; // Timer pre-scale high }; 关于定时器配置源码如下:    void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period) { Uint32 temp; // Initialize timer period: Timer->CPUFreqInMHz = Freq; Timer->PeriodInUSec = Period; temp = (long) (Freq * Period); Timer->RegsAddr->PRD.all = temp; // Set pre-scale counter to divide by 1 (SYSCLKOUT): Timer->RegsAddr->TPR.all = 0; Timer->RegsAddr->TPRH.all = 0; // Initialize timer control register: Timer->RegsAddr->TCR.bit.TSS = 1; // 1 = Stop timer, 0 = Start/Restart Timer Timer->RegsAddr->TCR.bit.TRB = 1; // 1 = reload timer Timer->RegsAddr->TCR.bit.SOFT = 1; Timer->RegsAddr->TCR.bit.FREE = 1; // Timer Free Run Timer->RegsAddr->TCR.bit.TIE = 1; // 0 = Disable/ 1 = Enable Timer Interrupt // Reset interrupt counter: Timer->InterruptCount = 0; }     用户设置:       ConfigCpuTimer(&CpuTimer0, 150, 1000000);//使用定时器0 ,时钟频率为150MHZ,计数值 到1M 。也就是说这样设置是产生一个一秒的中断     定时器中断处理函数设置:PIE_VECT_TABLE 中断向量表。在DSP2833x_PieVect.h中定义      PieVectTable.TINT0 = &cpu_timer0_isr;//往中断矢量表中填写一个指针。当定时时间到了就跳转到 ,当前指针指向的函数去执行代码。   定时器0中断在中断向量表中的组1  2.在定时器中使用GPIO翻转寄存器GPXTOGGLE  实现LED闪烁  

  • 发表了主题帖: F28335的GPIO、定时器和SCI

    1、GPIO 通用目的I/O模块(GPIO模块)内部配有复杂逻辑多路开关控制电路和复用寄存器,将数字I/O(GPIO)引脚、片上所有外设输入输出引脚、外部接口(XINTF)地址总线、数据总线、控制总线引脚在器件封装引脚上实现复用。 共88个GPIO,通过寄存器GPIOxMUX(x=A,B,C)进行设置。 GPIO分为3组,A端口对应引脚GPIO0~GPIO31(32位),B端口对应引脚GPIO32~GPIO63(32位),C端口对应引脚GPIO64~GPIO74(24位)。 当被配置为数字输入引脚时,具有输入滤波功能,通过GPIOSEL资格寄存器设定采样窗口宽度,对输入电平的干扰脉冲进行滤波。 外部中断输入引脚XINT1~XINT7、不可屏蔽中断输入引脚XNMI是可编程的GPIO复用引脚。 2、定时器 F28335内嵌3个结构完全相同的32位CPU定时器:CPUTimer0/1/2,其中用户可用CPUTimer0/1,CPUTimer2留给DSP/BIOS用,若用户应用系统不用DSP/BIOS,CPUTimer2可用供用户使用。 (1)32位减1计数寄存器和32位周期寄存器(存放定时计数常数,每当32位减1计数寄存器下溢时,用定时计数常数重载32位减1计数寄存器) (2)16位分频减1计数寄存器和16位分频寄存器(存放分频计数常数,每当16位分频减1计数寄存器下溢时,用分频计数常数重载16位分频减1计数寄存器)。 (3)CPUTimer0中断请求通过PIE组1(连接到INT1)扩展。CPUTimer1不通过PIE扩展,与XINT13(外部中断输入线)复用连接到INT13。CPUTimer2不通过PIE扩展,直接连接到INT14。 3、SCI F28335片上集成3个独立SCI模块:SCIA/B/C。 (1)传输字符格式可编程设置1位起始位。可编程字符长度1~8位,通常设置8位。可选的1位奇偶校验位或无奇偶校验位。可编程停止位1~2位,通常设置1位。 (2)4 种出错检测标志位:奇偶校验错、溢出错、帧格式错、间断检测错。 (3)13个SCI模块相关控制寄存器(都是16位字长寄存器的低8位有效,读高8位全零,写高8位无效),位于首地址7050H的外设帧2。 (4)2种唤醒多处理器通信模式:空闲线模式和地址位模式。 (5)半双工或全双工通信模式。 (6)双缓冲接收和发送功能。 (7)发送器和接收器可以通过中断驱动或利用状态标志位查询算法完成一帧数据的收发。 (8)发送和接收有单独的中断使能位,间断中断除外(BRKDT)。 (9)异步数据传输格式为不归零码(NRZ)。

  • 发表了主题帖: F28335 的控制模块

    F28335 的控制模块用于控制DSP的低功耗模式和监视CPU运行状态。包括:振荡器电路(SOC)、锁相环电路(PLL)、低功耗控制电路、看门狗电路、系统配置寄存器、外设模块时钟控制器。 系统控制模块的主要特性包括以下内容。 1.时钟电路的振荡器频率(SOCCLK)配置模式   (1)内部振荡器模式。通过X1和X2引脚外接30MHz无源晶振。   (2)外部3.3V振荡器配置模式。通过XCLKIN引脚外接3.3V振荡器频率。X2引脚应留悬空、X1引脚应连接到低电平。   (3)外部1.9V振荡器配置模式。通过X1引脚外接1.9V振荡器频率。X2引脚应留悬空、XCLKIN引脚应连接到低电平。 2.锁相环电路配置模式 (1)PLL关闭模式(PLL模块断电,在进入该模式前,应将PLLCR写入零值。) (2)PLL旁路模式(上电复位默认状态) (3)PLL使能模式(向PLLCR写非零值后,自动进入该模式。) 3.时钟信号检测电路 用来检测振荡器频率是否丢失。若丢失,时钟信号检测电路将产生一个内部系统复位信号,对CPU和片上外设复位。 4.低功耗模式 (1)空闲模式(时钟电路和系统时钟频率正常工作,唤醒方式主要是被使能的任何有效中断请求。系统复位信号。看门狗中断信号。) (2)备用模式(时钟电路正常工作,系统时钟频率关闭,唤醒方式主要是指定GPIOA端口符合低电平宽度的唤醒设备。系统复位信号。看门狗中断信号。) (3)暂停模式(时钟电路和系统时钟频率均关闭,唤醒方式主要是指定GPIOA端口符合低电平宽度的唤醒设备。系统复位信号。)

  • 发表了主题帖: F28335 存储器映射

    如图,为f28335的储存器映射图。10个片上SRAM(M1,M0,L0~L7),从XINTF外部接口扩展外部储存器空间。 M0的片上储存块地址范围是0x000040~0x003FF(1K×16位),M1块的地址范围是0x000400~0x0007FF(1K×16位)可为通用ROM,上电复位后M0被编译器作为储存数据,堆栈指针从M1开始。 L0~L3储存块为4K×16位,且受安全密码保护,均可配置为程序储存器。 L4~L7储存块为4K×16位,为SARAM块,也可以作为DAM储存块。 F28335片上有256K×16位的FLASH,分为8个扇区。  F28335片上包含1K×16位的一次编程ROM,地址范围为0x380400~0x3807FF。 安全代码模块(CodeSecurityModule,CSM)位于DSP的片上FLASH的最后8个单元地址0x33FFF8-0x3FFFF(8×16位)。用户填写128位密码之后,DSP片上的受安全代码保护的区域(简称安全存储器)就无法通过DSP的JTAG接口进行读取查看,也不能拷贝未授权的DSP片上FLASH、L0~L3、OTP等受代码模块保护的代码或数据

  • 发表了主题帖: DSP28335使用问题

       TI 的DSP为了提高安全性能,将很多关键寄存器作了保护处理。通过状态寄存器1(ST1)的位6设置与复位,来决定是否允许DSP指令对关键寄存器进行操作。这些关键寄存器包括:器件仿真寄存器、FLASH寄存器、CSM寄存器、PIE矢量表、系统控制寄存器、GPIOMux寄存器、eCAN寄存器的一部分。     DSP由于在上电复位之后,状态寄存器基本上都是清零,而这样的状态下正是上述特殊寄存器禁止改写的状态。为了能够对这些特殊寄存器进行初始化,所以在对上述特殊寄存器进行改写之前,一定要执行汇编指令asm(“EALLOW”)或者宏定义EALLOW来设置状态寄存器1的C6位,在设置完寄存器之后,一定要注意执行汇编指令asm(“EDIS”)或者宏定义EDIS来清除状态寄存器1的C6位。

  • 发表了主题帖: TMS320F28XXX的程序段从flash复制到ram中运行

            这个应用报告和相关的代码提供了一种把编译后的程序段从TMS320F28xxx的flash复制到ram的功能,这样可以提高代码的运行速度。这个解决方案在直接启动之后,进入c_int00 ——C语言代码运行之前实现此功能。   1.引言: 在许多应用中,代码的执行速度是至关重要的。例如在医疗,监控,电机控制等等一些对时间有严格要求的终端设备。许多应用使用TMS320F28xxx DSCs是因为它的内置flash储存器。内置flash是TMS320F28xxx的一个优势,因为它使得设计者不需要外接flash来储存代码。使用内部flash缺点是访问Flash需要等待状态,这使得程序的运行变慢。在大多数应用中,这不是一个问题。其他一些应用中可能会为了获得最高的运行速度要求无等待状态。内部RAM存储器具有零等待状态,它是易失性存储器。所以,引导的初始化代码段不可以存储在此存储器中。 现在提供的解决方案,使得设计者能够在运行时把被编译器初始化的代码段从flash复制到ram里,获得最大的运行速度。这使代码执行从多达15个等待状态的提升到0等待状态。另一种解决方案是只将某些函数从Flash复制到RAM。详见:《Running an Application from Internal Flash Memory on the TMS320F28xx DSP》 (SPRA958)。这种方法应该使用在大多数使用C2000™ DSC的应用上,其他要求严格的时序和连续的零等待状态的应用程序应采用这里提出的解决方案。 编写汇编程序来完成代码从Flash到RAM的复制。该汇编代码在复位向量后调用c_int00之前执行。这保证了在c_int00调用mian()之前完成复制。 有一些工程比较小,可以把所有初始化了的段都复制到ram。然而,其他一些工程的初始化了的段比所有的内部ram还要大。这些工程可能不可以把所有的初始化了的段都复制到ram,但是用这种方法复制其中一部分段。   2.编译的代码段: 编译器生成的包含代码和数据的多个部分,称为段。这下段被分为两个不同的组:初始化了的和没被初始化的,初始化的部分是由所有的代码,常量和初始化表组成的。下表列出了由编译器产生的初始化段。   没初始化的段是由未初始化的变量,堆栈和malloc产生的内存。下表列出了由编译器产生的没初始化段。 一旦编译器生成的这些段,连接器会从各个源文件中取出这些段,并结合它们来创建一个输出文件。连接器命令文件(.cmd)就是用来告诉连接器去哪里找这些段的。初始化段必须分配到非易失性存储器,如flash/ ROM,当电源被撤除时,程序不会消失。未初始化的段可以被分配到RAM中,因为它们是在代码执行期间被初始化的。 关于更多编译段和连接的信息,请参见:《TMS320C28x Assembly Language Tools User’s Guide 》(SPRU513) 和《 the TMS320C28x Optimizing C/C++ Compiler User’s Guide》(SPRU514)。 德州仪器(TI)提供了多个例子显示如何使用链接器命令文件分配编译段。其中一个就是《Running an Application from Internal Flash Memory on the TMS320F28xx DSP 》(SPRA958)。此应用文档提供的例子,演示了使用基于RAM和Flash的项目的链接器命令文件。   3.软件:      本应用文档相关的代码文件,包括修改后的版本的CodeStartBranch.asm文件和非DSP/BIOS™项目用的文件DSP28xxx_SectionCopy_nonBIOS.asm,由the C/C++ Header Files and Peripheral Examples提供。每个TMS320F28xxx处理器都提供了现成的连接器命令文件。提供的示例项目演示了如何使用这些文件。本应用文档以TMS320F2808为例。 该软件独立存放于F28xxx_Flash_to_Ram文件夹中。代码使用的来自the C/C++ Header Files and Peripheral Examples的几个文件,经过了Code Composer Studio™ 3.3和F28xxx代码生成工具5.0.0B3版本的测试。   3.描述: 一般的程序流程是这样子的:code_start->wd_disable->copy_sections->c_int00->mian() 。这个软件流程比标准的软件流程仅仅多了调用复制代码段函数。标准的软件流程:code_start->wd_disable->c_int00->mian()。   程序开始和关闭看门狗: code_start 和wd_disable 的运行代码由DSP28xxx_CodeStartBranch.asm文件提供。上电后,code_start正常执行,因为它被分配给Flash的引导地址的0x3F7FF6。详见:《Running an Application from Internal Flash Memory on the TMS320F28xx DSP 》(SPRA958) WD_DISABLE .set 1 ;set to 1 to disable WD, else set to 0 .ref copy_sections .global code_start *********************************************************************** * Function: codestart section * * Description: Branch to code starting point *********************************************************************** .sect "codestart" code_start: .if WD_DISABLE == 1 LB wd_disable ;Branch to watchdog disable code .else LB copy_sections ;Branch to copy_sections .endif 这个函数从the C/C++ Header Files and Peripheral Examples提供的CodeStartBranch.asm文件修改而来,只是第二个调用用copy_sections代替了_c_int00。这个调用仅仅在WD_DISABLE为0时执行。上面的代码,WD_DISABLE 被设置为1。这使得wd_disable运行。wd_disable的代码如下: *********************************************************************** * Function: wd_disable * * Description: Disables the watchdog timer *********************************************************************** .if WD_DISABLE == 1 .sect "wddisable" wd_disable: SETC OBJMODE ;Set OBJMODE for 28x object code EALLOW ;Enable EALLOW protected register access MOVZ DP, #7029h>>6 ;Set data page for WDCR register MOV @7029h, #0068h ;Set WDDIS bit in WDCR to disable WD EDIS ;Disable EALLOW protected register access LB copy_sections ;Branch to copy_sections .endif 这要求看门狗在_sections和c_int00函数运行期间被除能,否则,看门狗可能会在进入main()之前超时。这个函数也是从the C/C++ Header Files and Peripheral Examples提供的CodeStartBranch.asm文件修改而来,只是用copy_sections代替了_c_int00。   Copy_sections: DSP28xxx_SectionCopy_nonBIOS.asm文件提供了copy_sections的代码,第一次运行到这里,看门狗是关闭的,段已经准备好被复制,段大小被存放在累加器,装载地址放在XAR6中,执行地址放在XAR7中,这个功能例子如下: MOVL XAR5,#_text_size ; Store Section Size in XAR5 MOVL ACC,@XAR5 ; Move Section Size to ACC MOVL XAR6,#_text_loadstart ; Store Load Starting Address in XAR6 MOVL XAR7,#_text_runstart ; Store Run Address in XAR7 LCR copy ; Branch to Copy 段的大小,装载开始标志,执行开始标志都由连接器产生,这是在内存分配 -链接器命令文件一节讨论。 在地址和段长度都被存放好之后,copy程序被调用来确定段是否被编译器产生,这由检测累加器是否为0来确定。 copy: B return,EQ ; Return if ACC is Zero (No section to copy) RPT AL ; Copy Section From Load Address to || PWRITE *XAR7, *XAR6++ ; Run Address return: LRETR ; Return 如果累加器为0,程序会返回到调用前的地址,如果累加器不为0,有段需要被复制。这用上面所示的PWRITE指令来实现,PWRITE复制XAR6指向的存储器的内容到XAR7指向的内容。在这里,就是复制装载代码的地址的内容到运行代码的地址。这样,一直到累加器为0,完成整个段的复制,当所有段都被复制完,程序就会跳到c_int00,如下: LB _c_int00 ; Branch to start of boot.asm in RTS library 到这里,C语言环境被建立,main()是可进去的。 完整的copy_sections程序请参见相关文件夹中的DSP28xxx_SectionCopy_nonBIOS.asm。 内存分配 - 连接命令文件(.cmd): 如第二节所述,连接命令文件(.cmd)是用来告诉连接器怎么分配编译器产生的段的。The C/C++ Header Files and Peripheral Examples提供了标准的连接命令文件(.cmd)。 相关代码文件中提供了三个链接器命令文件用于配置内存分配。 · F280xx_nonBIOS_flash.cmd · F281x_nonBIOS_flash.cmd · F2833x_nonBIOS_flash.cmd 每个文件一般都用相同的方法编写,只是在存储器方面有很小的一些差异(特殊设备)。连接命令文件(.cmd)的Memory部分是根据设备的内存空间来连接编译好的段的。详情参见具体控制器的数据手册。      TMS320F28xxx系列控制器内置RAM,可以被分配为一个单独的段,或者更多的段,因为它是连续的存储器映射。如上图所示,F2808有映射到存储器空间的L0,L1和H0 SARAMs,允许生成一个大的内存块,这个块可以被CMD文件的MEMORY部分如下定义: RAM_H0L0L1 : origin = 0x008000, length = 0x004000 其余的也可以定义在MEMORY部分,完整的内存分配,请参见相关文件中的CMD文件。 链接器命令文件的第二部分是SECTIONS。这是实际编译器把段连接到的存储区。所有DSP28xxx_CodeStartBranch.asm 和 DSP28xxx_SectionCopy_nonBIOS.asm的段都被装载到flash中运行,这部分如下所示分配: codestart : > BEGIN_FLASH, PAGE = 0 wddisable : > FLASH_AB, PAGE = 0 copysections : > FLASH_AB, PAGE = 0 其他被初始化的段被下载到flash,但是在ram中运行。这是通过load和run指令来实现。下面展示一个例子: .text : LOAD = FLASH_AB, PAGE = 0 RUN = RAM_H0L0L1,PAGE = 0 LOAD_START(_text_loadstart), RUN_START(_text_runstart), SIZE(_text_size) 为了获得与一个段相关联的特定地址,如上所示,使用了LOAD_START, RUN_START, 和SIZE指令。这些指令的地址和大小在DSP28xxx_SectionCopy_nonBIOS.asm文件使用到,用以在复制过程中指向正确的地址。DSP28xxx_SectionCopy_nonBIOS.asm把这些值创建为全局变量,如下图所示 .global _cinit_loadstart, _cinit_runstart, _cinit_size .global _const_loadstart, _const_runstart, _const_size .global _econst_loadstart, _econst_runstart, _econst_size .global _pinit_loadstart, _pinit_runstart, _pinit_size .global _switch_loadstart, _switch_runstart, _switch_size .global _text_loadstart, _text_runstart, _text_size 测试例子: 提供的示例在TMS320F2812,TMS320F2808,TMS320F28335eZdsp开发板上进行了测试。板子上LED的闪烁可以从视觉上证实程序是否正确运行。下面的程序是基于F2808eZdsp评估板设计和测试的。同样的,这种方法可以用于其他eZdsp开发板。     Code Composer Studio环境: 1.使用USB线连接F2808eZdsp开发板到PC,接上电源线给板子供电。 2.打开Code Composer Studio,设置F2808 eZdsp 仿真器。 3.打开和编译Example_280xx_Flash_to_RAM_nonBIOS.pjt。 4.下载.out文件到芯片的flash中。 5.调试程序(debug)。 6.运行程序(run)。   在eZdsp电路板上的LED应闪烁,表示程序正在运行。   应用: 现有的Flash应用程序可以很容易地通过移植相关代码文件来实现此功能。基本的移植步骤如下: 1.用DSP28xxx_CodeStartBranch.asm替换CodeStartBranch.asm。 2.在工程中添加DSP28xxx_SectionCopy_nonBIOS.asm文件。 3.用特殊生成的CMD文件代替现有的CMD文件。   这个基本步骤不适用于一些特殊情况,比如用户自己定义的段,等   应用例子: 为了演示的应用程序集成的过程,在C280x,C2801x C / C ++头文件和外设示例的Example_2808_Flash.pjt中使用下列步骤移植。 1.下载安装C280x, C2801x C/C++ Header Files and Peripheral Examples。 2.如上所述连接板,打开项目文件。 3.删除项目中的DSP280x_CodeStartBranch.asm文件,在项目中添加DSP28xxx_CodeStartBranch.asm文件。 4.在项目中添加DSP28xxx_SectionCopy_nonBIOS.asm文件。 5.删除项目中的cmd文件,在项目中添加F280xx_nonBIOS_flash.cmd文件。 6.把DSP280x_usDelay.asm中的.sect “ramfuncs”改为.text,使DSP28x_usDelay在被分配在.text段中。 7.删除DSP280x_SysCtrl.c文件中的#pragma CODE_SECTION(InitFlash, “ramfuncs”);。使得InitFlash( )函数被分配到.text而不是ramfuncs。 8.删除Example_280xFlash.c文件中的#pragma CODE_SECTION(epwm1_timer_isr, “ramfuncs”);和#pragma CODE_SECTION(epwm2_timer_isr, “ramfuncs”);。使得中断服务函数被分配到.text而不是ramfuncs。 9.删除Example_280xFlash.c文件中的MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart)注意:这个已经不需要和 InitFlash( )。由于代码已经被复制到RAM,这些是不需要的了。 10.如上所述,编译连接程序,把程序下到芯片里运行。 在eZdsp电路板上的LED应闪烁,表示程序正在运行。 存储空间占用:       因为仅仅在DSP28xxx_SectionCopy_nonBIOS.asm文件中增加了copy_sections的代码。增加的占用的片内flash为0x3C。code_start 和wd_disable函数没有增加额外的代码,他们本来就在C/C++ Header Files and Peripheral Examples的所用项目中被使用。 测试: 因为这个功能开机后直接实现,闪存等待状态,锁相环(PLL)都没有配置,因此,它们都运行在默认值。Flash等待状态为15个周期,对于F280xx/F281x设备SYSCLKOUT为OSCCLK/2,对于F2833x设备SYSCLKOUT为OSCCLK/ 4。使用Code Composer Studio的分析功能可以测量运行时间。下表给出了每个F28xxx控制器从启动到main()函数的第一个指令所用的时间,如下所示,由于个平台的代码长度和系统时钟不一样,他们的运行时间也不一样。   限制: 此实现的限制因素为使用的TMS320F28xxx控制器内部RAM的大小。这限制了那些工程可以使用这种方法,如果工程太大,以至于没法放进RAM里,这种方法是不能用的。(除非外扩RAM)   建议: 有一些项目需要这种功能,但不是所有被初始化段都要复制到RAM或者没有足够的RAM放下所有的段。仅仅需要复制应用代码本身。这种情况下,仅仅需要复制.text段到RAM。这样子,可以把DSP28xxx_SectionCopy_nonBIOS.asm文件和cmd文件中复制其他段的代码删掉,把其他段放在flash中运行。减少flash的占用空间和缩短了运行到main()的时间。 应该确定应用程序可以处理复制代码执行时间的一点滞后。如果应用程序不能处理这段时间,可以使用Running an Application from Internal Flash Memory on the TMS320F28xx DSP (SPRA958)中的方法复制一部分主要的代码到ram。 如果使用DSP的引导,建议使用Running an Application from Internal Flash Memory on the TMS320F28xx DSP (SPRA958)中的方法复制一部分主要的代码到ram。一个使用DSP / BIOS的项目,通常是一个较大的项目,不建议使用此方案。 结语: 这份应用文档展示,在建立C语言环境之前,通过把flash的代码复制到ram,可以使TMS320F28xxx的控制器实现零等待状态运行。这方案给出了代码和存储空间的限制,为设计者提供了实现了这种功能的相关文件。      

  • 发表了主题帖: DSP28335—程序从flash复制到ram里的两种情况:部分复制和全部复制

          DSP从内存RAM中取指令的速度要比从flash中取指令要快好多倍,但是RAM的缺陷限制了其不能存储用户程序代码,因为RAM掉电会丢失数据,但是其速度要快,而flash内信息掉电不丢失,因此可以保存用户编程的代码,但是其运算速度使得在一些实时性要求高或者对时间要求苛刻的场合不能满足要求。如果能够将两者有机的结合到一起,从而可以解决这两者之间的矛盾。       从片内flash搬运到RAM中的方法有两种不同的选择,一种是将flash中部分代码搬运到RAM中运行;另一种便是将flash的所有程序代码都搬运到RAM中运行。前者利用#pragma CODE_SECTION(cpu_timer0_isr, "ramfuncs");来声明将所要搬运的函数在flash上电初始化时自动将声明的函数搬运到RAM的ramfuncs段中,此方法也可以将所有的函数代码都搬运到RAM中,但是,这无疑有点麻烦,有多少个函数就需要写多少条这样的语句,而且也只是搬运了函数代码,其他的初始化数据段没有搬运,但是这种方法可以在用户程序太大以至于RAM中无法将所有代码都容纳下的情况下,将部分主要的要求时间苛刻的函数搬运到RAM中运行以提高系统性能,例如一些中断函数。第二种方法可以在用户编写代码都能被RAM所容纳下的情况下提高系统整体的性能,将flash代码全部搬运到RAM中。但是当代码不能被RAM所容纳时此方法编不在可行,只有硬件外扩RAM才行。下面就介绍一下这两种方法的具体实现方法: 方法: 1、 cmd定义: ramfuncs            : LOAD = FLASHJ,  PAGE = 0                          RUN = RAMH0,  PAGE = 0                          LOAD_START(_RamfuncsLoadStart),                          LOAD_END(_RamfuncsLoadEnd),                          RUN_START(_RamfuncsRunStart) 2、定义变量(装载或运行的起始地址) extern Uint16 RamfuncsLoadStart; extern Uint16 RamfuncsLoadEnd; extern Uint16 RamfuncsRunStart; 3、把要拷贝到RAM里的函数(eva_timer1_isr,eva_timer2_isr...)定义到段ramfuncs   #pragma CODE_SECTION(eva_timer1_isr, "ramfuncs");   #pragma CODE_SECTION(eva_timer2_isr, "ramfuncs");   #pragma CODE_SECTION(evb_timer3_isr, "ramfuncs"); // 声明中断函数   interrupt void eva_timer1_isr(void);   interrupt void eva_timer2_isr(void);   interrupt void evb_timer3_isr(void);   interrupt void evb_timer4_isr(void); //初始化flash 控制寄存器函数为 void InitFlash(void) {         //函数内容省略,可参考TI提供的函数即可 }   4、在主函数中执行调用以下函数        MemCopy(&RamfuncsLoadStart,&RamfuncsLoadEnd,  &RamfuncsRunStart);       InitFlash(); 至此便将声明的中断函数在flash上电初始化时自动搬运到RAM中运行。

  • 2020-08-06
  • 发表了主题帖: [常见问题解答] F05 FlashC2000器件具有“F05 flash”吗?

    问:什么是闪存扇区(flash sector)? 它们记录在哪里? 答: 每个扇区的存储位置记录于数据手册存储映射中。 一个flash bank由多个扇区组成。 扇区大小与闪存的物理架构相对应,且大小不能更改。 扇区是可擦除的最小闪存区域。例如,您可擦除整个扇区“A”,但无法擦除扇区A中的单字。 您可在链接器命令文件中合并扇区以创建更大的.text段。这不会改变扇区是可擦除的最小数量的事实。   问:为什么不能在闪存中设置两个以上的断点?为什么不能在闪存中单步执行代码? 答: Code Composer Studio支持软件断点和硬件断点。调试从闪存运行的代码时,必须使用硬件断点。基于F05的器件可访问2个硬件断点。单步也需要设置硬件断点。 Code Composer Studio自动设置两个断点:(a)程序结束和(b)CIO(用于printf)。这样可防止您在调试Flash中的应用程序时遇到任何断点。可通过在debugger options->program/memory load选项中禁用“CIO”和“end of program”断点来更改此行为。 应该注意:如按照以下步骤操作,您将无法输出CIO文本(例如printf等)。  这也将防止程序在退出时自动停止。 注意:较新的C28x基器件(例如F28004x)没有此限制!!这些器件具有称之为ERAD的模块。有关更多详细信息,请查阅数据手册和TRM。 问:我想获得flash API源代码。  TI会分配吗? 答: TI通常不会分配源代码。原因在于更改代码可能会损害器件中的闪存。更改的API不能在应用程序中使用。如要创建一个闪存编程解决方案,闪存API库的使用必须符合TI的规定。 当应用程序用于军事、航空或医疗领域且用户有正当理由需要使用源代码进行认证时,可通过与TI签署许可协议获得源代码。如果您的情况属于此类,请联系您的TI销售人员或分销代表或在这些论坛中发帖寻求帮助。  

  • 发表了主题帖: 【分享】F28002x介绍

    使用第三代技术F28002x新特点: 主频全系列100MHz并集成三角函数与浮点计算单元 支持快速整型除法指令集 支持非线性PID控制 内部集成2个独立12Bit, 3.45MSPS ADC实现同步采用 高速窗口比较器同时实现高低边50ns PWM保护延时 DCSM模块实现双代码安全 第四代PWM技术增加更多功能 灵活死区时间配置 PWM可根据触发特定Trip事件计数等 专有捕获模块实现谷底导通,提高PFC轻载效率 增加指令预读取提高代码在Flash执行效率达到主频84% 可配置逻辑模块CLB集成LUT与状态机可实现逻辑控制功能 实现QEP,PWM,绝对值编码器扩展。 更多外设接口 集成快速串口通信FSI  实现100Mbps通信 集成CAN通信  

  • 发表了主题帖: C2000™关键技术指南

    本应用报告旨在对 C2000 微控制器单元 (MCU) 中与实时控制系统相关并使其性能脱颖而出的器件进行更深 入的研究。重点 介绍了 德州仪器 (TI) 认为会对整体系统性能产生明显影响以及可增加 MCU 带宽的特性。 本文档对系统的特定方面进行了扩展研究,并在所涉及主题方面对其进行了改进。最后,针对每个主题提供 了适用参考文件以及指向分离式器件型号 (PN)、参考设计和演示套件的链接。

  • 回复了主题帖: 在 TMS320F28004x 和 TMS320F28002x 之间进行迁移

  • 发表了主题帖: 在 TMS320F28004x 和 TMS320F28002x 之间进行迁移

         本迁移指南介绍了在F28004x 和F28002x C2000™MCU 之间迁移时需要注意的硬件和软件差异。本文档提供了上述两个MCU 的方框图,直观地显示了二者的异同点,还在器件比较表中突出显示了两种器件采用不同封装时的独特功能。采用64-PM 封装可以很好地开始迁移,该封装引脚与F28004x 和F28002x 二者兼容,因此添加了64-PM PCB 硬件部分。2 节讨论了在采用64-PM 封装的F28004x 和F28002x 之间进行迁移的硬件注意事项。数字通用输入/输出(GPIO) 和模拟多路复用比较表显示了两种MCU 的引脚功能,这为在两种器件之间的迁移提供了有关硬件设计和信号路由的良好参考。最后,只提供EABI 格式的F28002x 软件支持。4 节对EABI 迁移进行了讨论。

统计信息

已有1332人来访过

  • 芯币:10535
  • 好友:--
  • 主题:2975
  • 回复:723
  • 课时:--
  • 资源:19

留言

你需要登录后才可以留言 登录 | 注册


博浩元电子 2018-10-25
不错,干货
查看全部
可以免费送彩金的网站 mg游戏送彩金无需申请 足彩送彩金 棋牌正版送彩金 澳客彩票 网上现金赌博送彩金 澳门真人网上娱乐送彩金 电子娱乐送彩金论坛 67娱乐系统 ag送彩金