fish001

  • 2020-08-05
  • 发表了主题帖: 数字信号处理器(DSP) – 机器视觉的应用

        DSP 为传感器到服务器的各种应用带来计算性能、实时处理和能效。数字信号处理器有哪些用途?查看以下这些针对多种 DSP 应用的解决方案。     机器视觉 (MV) 是指在工业应用和非工业应用中,根据图像采集和分析处理结果为设备功能执行提供操作引导。从本质上说,这是为不同的"眼盲"设备提供"视力"或"视觉"。这样做可以显著增强设备的功能,从而提高产品质量、提高生产力并降低成本。机器视觉广泛用于工厂自动化中的自动检查和机器人引导。机器视觉还用于安保系统、验钞机和打印机/扫描仪。     TI 为机器视觉应用提供广泛的处理解决方案。TI 基于 DSP 的解决方案凭借可扩展的解决方案,从单一摄像头解决方案到诸如晶圆检查应用中使用的大型高性能计算系统,提供业界出色的实时嵌入式分析处理性能。TI 还在我们免费的 Processor SDK 中提供易于使用的软件库来加快机器视觉解决方案的开发。 航空电子设备和国防 TI 的商业处理器(包括单核和多核 Arm®、DSP 及 Arm®+DSP)非常适合国防和航空电子应用,其中包括雷达、电子战、航空电子设备和软件定义无线电 (SDR)。我们的处理器支持工业温度范围、片上存储器上的 ECC、安全启动、安全特性。软件支持包括主线 Linux、TI RTOS 和大部分商业 RTOS。 尺寸、重量和功耗 (SWAP) 国防和航空电子中的许多应用具有严格的尺寸、重量和功耗要求,并需要在规定的 SWaP 预算范围内提供所需性能的优化 SoC。TI 致力于采用标准 Arm® 内核和 TI C66x DSP 内核创建从单核到多核异构 SoC 的可扩展器件系列,旨在提供出色的每瓦性能。  

  • 发表了主题帖: TI DSP的选型都有哪些?

    TI公司现在主推四大系列DSP 1)C5000系列(定点、低功耗):C54X,C54XX,C55X 相比其它系列的主要特点是低功耗,所以最适合个人与便携式上网以及无线通信应用,如手机、PDA、GPS等应用。处理速度在80MIPS--400MIPS之间。C54XX和C55XX 一般只具有McBSP同步串口、HPI并行接口、定时器、DMA等外设。值得注意的是C55XX提供了EMIF外部存储器扩展接口,可以直接使用SDRAM,而C54XX则不能直接使用。两个系列的数字IO都只有两条。 2)C2000系列(定点、控制器):C20X,F20X,F24X,F24XX ,C28x该系芯片具有大量外设资源,如:A/D、定时器、各种串口(同步和异步),WATCHDOG、CAN总线/PWM发生器、数字IO脚等。是针对控制应用最佳化的DSP,在TI所有的DSP中,只有C2000有FLASH,也只有该系列有异步串口可以和PC的UART相连。 3)C6000系列:C62XX,C67XX,C64X 该系列以高性能著称,最适合宽带网络和数字影像应用。32bit,其中:C62XX和C64X是定点系列,C67XX 是浮点系列。该系列提供EMIF扩展存储器接口。该系列只提供BGA封 装,只能制作多层PCB。且功耗较大。同为浮点系列的C3X中的VC33现在虽非主流产品,但也仍在广泛使用,但其速度较低,最高在150MIPS。 4)OMAP系列:OMAP处理器集成ARM的命令及控制功能,另外还提供DSP 的低功耗实时信号处理能力,最适合移动上网设备和多媒体家电。 其他系列的DSP曾经有过风光,但现在都非TI主推产品了,除了C3X系列外,其他基本处于淘汰阶段,如:C3X的浮点系列:C30,C31,C32 C2X和C5X系列:C20,C25,C50。

  • 2020-08-04
  • 发表了主题帖: MSP432开发板串口调试

    先将串口调试好,便于下一步工作的展开。首先,查看TI提供的代码例子,这个例子就在TI的MSPWare代码包内。注释如下:   //****************************************************************************** //  MSP432P401 Demo - eUSCI_A0 UART echo at 9600 baud using BRCLK = 12MHz // // Description: This demo echoes back characters received via a PC serialport. //  SMCLK/DCO is used as a clock source and the device is put in LPM3 //  Theauto-clock enable feature is used by the eUSCI and SMCLK is turned off //  when theUART is idle and turned on when a receive edge is detected. //  Note thatlevel shifter hardware is needed to shift between RS232 and MSP //  voltagelevels. // //  Theexample code shows proper initialization of registers //  andinterrupts to receive and transmit data. //  To testcode in LPM3, disconnect the debugger. // // // //               MSP432P401 //            ----------------- //        /|\|                 | //          ||                 | //         --|RST              | //           |                 | //           |                 | //           |     P1.3/UCA0TXD|----> PC(echo) //           |     P1.2/UCA0RXD|<---- PC //           |                 | // //   Wei Zhao //   TexasInstruments Inc. //   October2015 (updated) | June 2014 (created) //   Builtwith Code Composer Studio V6.0 //****************************************************************************** 从以上信息我们可以看出,此段例程所要做的事情就是将板载串口配置成9600波特率工作的串口,并原样送回我们发送进去的数据。从示意图中我们可以看出,我们只需要一对收发线即可完成本实验。接下来分析其源代码。 #include "msp.h" int main(void) {   WDTCTL =WDTPW | WDTHOLD;               // Stopwatchdog timer     CS->KEY= 0x695A;                        //Unlock CS module for register access   CS->CTL0= 0;                            // Resettuning parameters   CS->CTL0= CS_CTL0_DCORSEL_3;                   //Set DCO to 12MHz (nominal, center of 8-16MHz range)                                          //Select ACLK = REFO, SMCLK = MCLK = DCO   CS->CTL1= CS_CTL1_SELA_2 | CS_CTL1_SELS_3 | CS_CTL1_SELM_3;   CS->KEY= 0;                             // LockCS module from unintended accesses     //Configure UART pins   P1SEL0 |=BIT2 | BIT3;                  // set2-UART pin as second function    __enable_interrupt();  NVIC->ISER[0] = 1 << ((EUSCIA0_IRQn) & 31); // EnableeUSCIA0 interrupt in NVIC module     //Configure UART   UCA0CTLW0|= UCSWRST;   UCA0CTLW0|= UCSSEL__SMCLK;             // PuteUSCI in reset   // BaudRate calculation   //12000000/(16*9600) = 78.125   //Fractional portion = 0.125   // User'sGuide Table 21-4: UCBRSx = 0x10   // UCBRFx =int ( (78.125-78)*16) = 2   UCA0BR0 =78;                           //12000000/16/9600   UCA0BR1 =0x00;   UCA0MCTLW= 0x1000 | UCOS16 | 0x0020;    //注意这一行的设定     UCA0CTLW0&= ~UCSWRST;                  //Initialize eUSCI   UCA0IE |=UCRXIE;                       // EnableUSCI_A0 RX interrupt     __sleep();  __no_operation();                      // For debugger }   // UART interrupt service routine void EUSCIA0_IRQHandler(void) {     if(UCA0IFG & UCRXIFG)     {      while(!(UCA0IFG&UCTXIFG));      UCA0TXBUF = UCA0RXBUF;      __no_operation();     } } 我们首先粗略地研究一下这段测试代码,忽略前半部分关于时钟设置的内容,检查我标记的注意行。UCA0MCTLW0寄存器的设定在芯片TechnicalReference Manual的745页,例程中基本是使用默认串口配置。串口通信波特率已经在前面代码中设定为9600。看明白了上述内容,就掌握了这块开发板串口的基本内容,有精力可以继续探索一下芯片手册,尝试串口的其他功能。重要提示,不要使用盗版ghost win7,这样会导致xds110板载调试器的驱动安装失败。

  • 发表了主题帖: MSP432E401Y电机编码器QEI模块

    /* DriverLib Includes */ #include <ti/devices/msp432e4/driverlib/driverlib.h> /* Standard Includes */ #include <stdint.h> #include <stdio.h> #include <stdbool.h> unsigned long  COUNT = 0; unsigned long  POS = 0; int  s; int d;   //******************************************************************** //QEI0初始化 int QEIInit (void) {     QEIConfigure(QEI0_BASE,(QEI_CONFIG_CAPTURE_A_B |QEI_CONFIG_NO_RESET|     QEI_CONFIG_QUADRATURE|QEI_CONFIG_NO_SWAP),10000000);//使用A,B通道共4个边沿计算位置    /* GPIOPadConfigSet(GPIO_PORTL_BASE, GPIO_PIN_1,     GPIO_STRENGTH_4MA,     GPIO_PIN_TYPE_STD);     GPIOPadConfigSet(GPIO_PORTL_BASE, GPIO_PIN_2,     GPIO_STRENGTH_4MA,     GPIO_PIN_TYPE_STD);     GPIOPadConfigSet(GPIO_PORTL_BASE, GPIO_PIN_3,     GPIO_STRENGTH_4MA,     GPIO_PIN_TYPE_STD);   */     GPIOPinTypeQEI(GPIO_PORTL_BASE,GPIO_PIN_1|GPIO_PIN_2);//配置PL1,PL2为PhA1,PhB1     QEIVelocityConfigure(QEI0_BASE, QEI_VELDIV_1, 120000000/100);//10ms     //使能速度计算,使能QEI     QEIVelocityEnable(QEI0_BASE);     QEIEnable(QEI0_BASE);     //速度计时器计时完成时触发中断     QEIIntEnable(QEI0_BASE,QEI_INTTIMER);     IntEnable(INT_QEI0);     return(0); } void QEI0_IRQHandler(void) {   QEIIntClear(QEI0_BASE, QEI_INTTIMER);   POS = QEIPositionGet(QEI0_BASE);   d = QEIDirectionGet(QEI0_BASE);     COUNT = QEIVelocityGet(QEI0_BASE);     s = (COUNT*6000)/2024;     printf("The Speed is %d .Velocity is %d.Direction is %d.\n",s,COUNT /4,d);     COUNT = 0;   }  int main(void) {     /* Configure the system clock for 120 MHz */     MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN |                                           SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480),                                           120000000);     MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0);//使能QEI0外设     MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);/*enable L port*/     MAP_IntEnable(INT_GPIOL);     GPIOPinConfigure(GPIO_PL1_PHA0);     GPIOPinConfigure(GPIO_PL2_PHB0);       QEIEnable(QEI0_BASE);//使能正交编码器QEI0     QEIInit();     while(1)     {     } }

  • 发表了主题帖: MSP430Ware使用笔记 初始化XT1

    1.平台说明 MSP430F5438 2.为什么使用MSPWare。 由于工作原因,学校中多使用STM32,STM32的DriverLib比较方便使用。初学MSP430重新回到了操作寄存器的时代,稍稍有点不适应。后来发现MSP也有DriverLib只是使用的人不多,就这范例文档一点一点摸索,并和寄存器操作相比较。经过了一段时间的努力也就熟悉了。 3.嵌入式系统编程趋势 个人认为,DriverLib会成为主流,这样可以缩短MCU使用的难度,在Flash和RAM容量不断提高的今天,不必去死抠每一个函数,如何更快上手MCU解决实际问题才是王道。刚刚推出市场的新MCU也具备DriverLib,缩短上手时间,更快占领市场。 4.示例代码,启动XT1。TI的示例代码中缺少初始化P7.0和P7.1外设功能的代码,所以无法运行。此处做了少许修改。 #include "inc/hw_memmap.h" #include "ucs.h" #include "wdt_a.h" #include "gpio.h" #include "sfr.h"   uint16_t status;   void main (void) {     // 停止看门狗     WDT_A_hold(WDT_A_BASE);       // P4.0保持输出状态     GPIO_setAsOutputPin(GPIO_PORT_P4,GPIO_PIN0);       // 初始化P7.0和P7.1为复用功能     GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_P7 , GPIO_PIN0 | GPIO_PIN1 );     // 启动XT1 并等待晶振所有错误标志位清楚     UCS_LFXT1Start( UCS_BASE , UCS_XT1_DRIVE0 , UCS_XCAP_3 );       // 使能全局中断     __bis_SR_register(GIE);       while(1)     {         // 翻转P4.0         GPIO_toggleOutputOnPin(GPIO_PORT_P4,GPIO_PIN0);         // 软件延时         __delay_cycles(1000000);     } } 如果使用了XT1或者XT2,那么调用UCS_getSMCLK、UCS_getMCLK、UCS_getACLK之前需要调用UCS_setExternalClockSource(UCS_BASE,XT1_CLK,XT2_CLK); 虽然对于这段代码而言UCS_getSMCLK等函数没有实际的作用,但这些函数对于设定UART或SPIder波特率还是很有帮助的。 修改后的代码如下: #include "inc/hw_memmap.h" #include "ucs.h" #include "wdt_a.h" #include "gpio.h" #include "sfr.h"   uint32_t clockValue_ACLK = 0; uint32_t clockValue_MCLK = 0; uint32_t clockValue_SMCLK = 0;   void main (void) {     // 停止看门狗     WDT_A_hold(WDT_A_BASE);       // P4.0保持输出状态     GPIO_setAsOutputPin(GPIO_PORT_P4,GPIO_PIN0);       // 初始化P7.0和P7.1为复用功能     GPIO_setAsPeripheralModuleFunctionInputPin( GPIO_PORT_P7 , GPIO_PIN0 | GPIO_PIN1 );     // 启动XT1,并等待晶振所有错误标志位清楚     UCS_LFXT1Start( UCS_BASE , UCS_XT1_DRIVE0 , UCS_XCAP_3 );       // 如果使用XT1或者XT2,需要调用该函数     UCS_setExternalClockSource(UCS_BASE,32768,8000000);     // 获得系统时钟,系统时钟,辅助时钟     clockValue_SMCLK = UCS_getSMCLK( UCS_BASE );     clockValue_MCLK = UCS_getMCLK( UCS_BASE );     clockValue_ACLK = UCS_getACLK( UCS_BASE );       // 使能全局中断     __bis_SR_register(GIE);       while(1)     {         // 翻转P4.0         GPIO_toggleOutputOnPin(GPIO_PORT_P4,GPIO_PIN0);         // 软件延时         __delay_cycles(1000000);     } } 默认情况,ACLK选择XT1时钟,此时XT1时钟为32768HZ,FLL参考时钟为XT1,倍频之后DCODIV为1048576Hz。SMCLK和MCLK的参考时钟均为DCODIV。

  • 发表了主题帖: msp432记录1-gpio使用

    其实看sdk里面的文档已经将使用方法说得很清楚了,记录一些问题 msp_exp432p401r.h中GPIO typedef enum MSP_EXP432P401R_GPIOName中的声明是和 .c文件中gpioPinConfigs的定义是一一对应的 通过调用GPIO_init()即可将GPIO初始化成gpioPinConfigs[ ]中的状态

  • 发表了主题帖: MSP432有关GPIO的配置问题

    个人认为GPIO函数主要分两类一类是GPIO中断配置函数 主要有以下几个参数设置大同小异,selectedPort可选有 GPIO_PORT_P1 GPIO_PORT_P2 GPIO_PORT_PA 而selectedPins可选有 GPIO_PIN0 GPIO_PIN1 GPIO_PIN2 GPIO_PIN3 GPIO_PIN4 GPIO_PIN5 GPIO_PIN6 GPIO_PIN7 GPIO_PIN8 GPIO_PIN9 GPIO_PIN10 GPIO_PIN11 GPIO_PIN12 GPIO_PIN13 GPIO_PIN14 GPIO_PIN15 //GPIO中断标志位清除 void GPIO_clearInterruptFlag (uint_fast8_t selectedPort, uint_fast16_t selectedPins) //GPIO边沿触发方式,edgeSelect有以下选择:GPIO_HIGH_TO_LOW_TRANSITION(下降沿触发) GPIO_LOW_TO_HIGH_TRANSITION(上升沿触发) void GPIO_interruptEdgeSelect (uint_fast8_t selectedPort, uint_fast16_t selectedPins, uint_fast8_t edgeSelect) //GPIO中断使能关闭 void GPIO_disableInterrupt (uint_fast8_t selectedPort, uint_fast16_t selectedPins) //GPIO中断使能 void GPIO_enableInterrupt (uint_fast8_t selectedPort, uint_fast16_t selectedPins) //GPIO获取中断使能标志位,返回(unsigned int)的一个数据 uint_fast16_t GPIO_getEnabledInterruptStatus (uint_fast8_t selectedPort) //GPIO获取IO中断标志位,返回(unsigned int)的一个数据 uint_fast16_t GPIO_getInterruptStatus (uint_fast8_t selectedPort, uint_fast16_t selectedPins) void GPIO_registerInterrupt (uint_fast8_t selectedPort, void(intHandler)(void))   //第二类就是普通GPIO口配置函数 uint8_t GPIO_getInputPinValue (uint_fast8_t selectedPort, uint_fast16_t selectedPins) void GPIO_setAsInputPin (uint_fast8_t selectedPort, uint_fast16_t selectedPins) void GPIO_setAsInputPinWithPullDownResistor (uint_fast8_t selectedPort, uint_fast16_t selectedPins) void GPIO_setAsInputPinWithPullUpResistor (uint_fast8_t selectedPort, uint_fast16_t selectedPins) void GPIO_setAsOutputPin (uint_fast8_t selectedPort, uint_fast16_t selectedPins) void GPIO_setAsPeripheralModuleFunctionInputPin (uint_fast8_t selectedPort, uint_fast16_t selectedPins, uint_fast8_t mode) void GPIO_setAsPeripheralModuleFunctionOutputPin (uint_fast8_t selectedPort, uint_fast16_t selectedPins, uint_fast8_t mode) void GPIO_setDriveStrengthHigh (uint_fast8_t selectedPort, uint_fast8_t selectedPins) void GPIO_setDriveStrengthLow (uint_fast8_t selectedPort, uint_fast8_t selectedPins) void GPIO_setOutputHighOnPin (uint_fast8_t selectedPort, uint_fast16_t selectedPins) void GPIO_setOutputLowOnPin (uint_fast8_t selectedPort, uint_fast16_t selectedPins) void GPIO_toggleOutputOnPin (uint_fast8_t selectedPort, uint_fast16_t selectedPins) void GPIO_unregisterInterrupt (uint_fast8_t selectedPort)

  • 2020-08-03
  • 发表了主题帖: msp430实现一个按键矩阵扫描和UART发送

    功能概述:        实现一个4x4按键矩阵,通过按键扫描,当有按键按下时,识别按键值,并通过UART串口发送,同时在lcd1602显示。 功能实现: 1.    按键扫描 void keyboardScan(){   P1OUT = 0xef;//P1.4 = 0   if((P1IN & 0x0f) != 0x0f){     delay_ms8M(5);//消抖     if((P1IN & 0x0f) != 0x0f){       if((P1IN & 0x01) == 0){ keyValue = '3';while((P1IN & 0x01) == 0);};       if((P1IN & 0x02) == 0){ keyValue = '7';while((P1IN & 0x02) == 0);};       if((P1IN & 0x04) == 0){ keyValue = 'B';while((P1IN & 0x04) == 0);};       if((P1IN & 0x08) == 0){ keyValue = 'F';while((P1IN & 0x08) == 0);};       keyboard_envent = ~keyboard_envent;     }   }   P1OUT = 0xdf;//P1.5 = 0   if((P1IN & 0x0f) != 0x0f){     delay_ms8M(5);//消抖     if((P1IN & 0x0f) != 0x0f){       if((P1IN & 0x01) == 0){ keyValue = '2';while((P1IN & 0x01) == 0);};       if((P1IN & 0x02) == 0){ keyValue = '6';while((P1IN & 0x02) == 0);};       if((P1IN & 0x04) == 0){ keyValue = 'A';while((P1IN & 0x04) == 0);};       if((P1IN & 0x08) == 0){ keyValue = 'E';while((P1IN & 0x08) == 0);};       keyboard_envent = ~keyboard_envent;     }   }   P1OUT = 0xbf;//P1.6 = 0   if((P1IN & 0x0f) != 0x0f){     delay_ms8M(5);//消抖     if((P1IN & 0x0f) != 0x0f){       if((P1IN & 0x01) == 0){ keyValue = '1';while((P1IN & 0x01) == 0);};       if((P1IN & 0x02) == 0){ keyValue = '5';while((P1IN & 0x02) == 0);};       if((P1IN & 0x04) == 0){ keyValue = '9';while((P1IN & 0x04) == 0);};       if((P1IN & 0x08) == 0){ keyValue = 'D';while((P1IN & 0x08) == 0);};       keyboard_envent = ~keyboard_envent;     }   }   P1OUT = 0x7f;//P1.7 = 0   if((P1IN & 0x0f) != 0x0f){     delay_ms8M(5);//消抖     if((P1IN & 0x0f) != 0x0f){       if((P1IN & 0x01) == 0){ keyValue = '0';while((P1IN & 0x01) == 0);};       if((P1IN & 0x02) == 0){ keyValue = '4';while((P1IN & 0x02) == 0);};       if((P1IN & 0x04) == 0){ keyValue = '8';while((P1IN & 0x04) == 0);};       if((P1IN & 0x08) == 0){ keyValue = 'C';while((P1IN & 0x08) == 0);};       keyboard_envent = ~keyboard_envent;     } <div>  }</div><div>}</div> 复制代码 2.    UART初始化 void uartInit(){   DCOCTL = 0;                                 BCSCTL1 = CALBC1_1MHZ;                    // 选择1MHZ作为波特率发生器输入时钟频率   DCOCTL = CALDCO_1MHZ;     P3SEL = 0X30;         // P3.4 TX    P3.5 RX   UCA0CTL1 |= UCSSEL_2;//clk = SMCLK 辅助时钟   select clock source   UCA0BR0 = 104;       // 1MHZ / 9600 = 104.17   UCA0BR1 = 0;         // baud rate 9600   UCA0MCTL = UCBRS0;//波特率调整  0.17 * 8 = 1.36 取整 1     UCA0CTL1 &= ~UCSWRST;              // 初始化USCI,复位释放,结束初始化 } 复制代码 3.    LCD1602初始化 void lcd1602Init(){   P3DIR |= BIT0 + BIT1 + BIT2;   dataout;   rst_en;   P1DIR = 0X70;   write_com(0x38);//8 bit data, doule line, 5x7 point matrix   write_com(0x0c);//open display, close cusor,close blink   write_com(0x06);//auto move to next char after write or read   write_com(0x01);//clear screen } 实现过程中遇到的问题: 1.    按键按下后会连续不断的发送,就算以很快的速度按下还是会发送两次。 解决办法:等待按键放开。 2.    Proteus虚拟终端关闭后再也打不开。 解决办法:感觉这是一个bug,只能重新建一个项目。

  • 发表了主题帖: MSP430单片机的8大输出方式

    1 输出模式0 输出模式:输出信号OUTx由每个捕获/比较模块的控制寄存器CCTLx中的OUTx位定义,并在写入该寄存器后立即更新。最终位OUTx直通。 2 输出模式1 置位模式:输出信号在TAR等于CCRx时置位,并保持置位到定时器复位或选择另一种输出模式为止。 3 输出模式2 PWM翻转/复位模式:输出在TAR的值等于CCRx时翻转,当TAR的值等于CCR0时复位。 4 输出模式3 PWM置位/复位模式:输出在TAR的值等于CCRx时置位,当TAR的值等于CCR0时复位。 5 输出模式4 翻转模式:输出电平在TAR的值等于CCRx时翻转,输出周期是定时器周期的2倍。 6 输出模式5 复位模式:输出在TAR的值等于CCRx时复位,并保持低电平直到选择另一种输出模式。 7 输出模式6 PWM翻转/置位模式:输出电平在TAR的值等于CCRx时翻转,当TAR值等于CCR0时置位。 8 输出模式7 PWM复位/置位模式:输出电平在TAR的值等于CCRx时复位,当TAR的值等于CCR0时置位。         MSP430系列单片机是TI1996年开始推向市场的一种16位超低功耗、具有精简指令集(RISC)的混合信号处理器,将多个不同功能的模拟电路、数字电路和微处理器集成在一个芯片上,以提供”单片机“解决方案,多用于需要电池供电的便携式仪器仪表中。         MSP430 系列单片机的各系列都集成了较丰富的片内外设。它们分别是看门狗(WDT)、模拟比较器A、定时器A0(TImer_A0)、定时器A1(TImer_A1)、定时器B0(TImer_B0)、UART、SPI、I2C、硬件乘法器、液晶驱动器、10位/12位ADC、16位Σ-Δ ADC、DMA、I/O端口、基本定时器(Basic Timer)、实时时钟(RTC)和USB控制器等若干外围模块的不同组合。其中,看门狗可以使程序失控时迅速复位;模拟比较器进行模拟电压的比较,配合定时器,可设计出A/D 转换器;16 位定时器(Timer_A 和 Timer_B)具有捕获/比较功能,大量的捕获/比较寄存器,可用于事件计数、时序发生、PWM等;有的器件更具有可实现异步、同步及多址访问串行通信接口可方便的实现多机通信等应用;具有较多的 I/O 端口,P0、P1、P2 端口能够接收外部上升沿或下降沿的中断输入;10/12位硬件 A/D 转换器有较高的转换速率,最高可达200kbps ,能够满足大多数数据采集应用;能直接驱动液晶多达 160 段;实现两路的 12 位D/A转换;硬件I2C串行总线接口实现存储器串行扩展;以及为了增加数据传输速度,而采用的DMA模块。MSP430 系列单片机的这些片内外设为系统的单片解决方案提供了极大的方便。

  • 发表了主题帖: MSP430低功耗模式-while循环失效

    如下代码实现MSP430G2553单片机两个led交替闪烁       #include <msp430.h>     /**     * main.c     */     int main(void)     {     WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer     P1DIR|=BIT0+BIT6;     P1OUT|=BIT0;     while(1)     {     unsigned int i;     i=50000;     while(i--);     P1OUT^=BIT0+BIT6;     }     } 发现灯光显示异常两灯常亮。 为什么呢?在老师帮助下了解了是因为Msp430这款板子默认的低功耗模式导致了cpu不干预而使这种while(i--)的空循环失效。 锚点锚点MSP430G2553单片机有6种功耗模式如下: 1、活动模式-----AM 正常的工作模式,这时CPU消耗的电能最大. 2、低功耗模式0-----LPM0 CPUOff置位,CPU停止活动,但外围模块继续工作,ACLK和MCLK信号保持活动,MCLK的锁频坏控制正常工作.有关控制位设置为:SCG0=0,SCG1=0,OscOff=0,CPUOff=1。 3、低功耗模式1-----LPM1 CPUOff置位,CPU停止活动,但外围模块继续工作,MCLK的锁频环控制停止工作,ACLK与MCLK保持活动,有关控制位设置为:SCG0=0,SCG1=1,OscOff=0,CPUOff=1。 4、低功耗模式2-----LPM2 CPUOff置位,CPU停止活动,但外围模块继续工作,MCLK的锁频环控制停止,ACLK活动,MCLK停止,有关控制位设置为:SCG0=0,SCG1=1,OscOff=0,CPUOff=1。 5、低功耗模式3-----LPM3 CPUOff置位,CPU停止活动,但外围模块继续工作,MCLK的锁频环控制和MCLK停止工作,DCO的DC发生器关闭,但ACLK信号仍保持活动,有关控制位设置为:SCG0=1,SCG1=1,OscOff=0,CPUOff=1。 6、低功耗模式4-----LPM4 CPUOff置位,CPU停止活动,但外围模块继续工作,MCLK的锁频环控制和MCLK停止工作,晶振停止,有关控制位设置为:SCG0=x,SCG1=x,OscOff=1,CPUOff=1。 处理器进入低功耗模式以后,一般由中断来唤醒。可以是外部中断,也可以是内部的定时器等中断。 锚点锚点而具体到上述问题从TI网站上查到相应的资料:翻译后如下 MSP430提供各种类型的定时器和时钟,可配置为无需CPU干预即可运行。当需要延迟时,可以利用其中一个定时器外设来产生这种延迟,而CPU不会保持活动状态。该方法显着降低了设备的功耗。这些定时器可使MSP430微控制器保持低功耗模式,直到定时器唤醒CPU。 风险,严重程度 在微控制器中,CPU是整体功耗的最大贡献者。当应用程序执行延迟时,如果CPU保持活动模式,则会浪费大量的功率和能量。 为什么会这样 当在项目中的任何代码文件中发现延迟时,将发出此注释。 检查代码中是否包含仅包含以下任一行的循环,而不包含任何其他代码:  __no_operation();  _NOP(); 任何空循环。例如: 锚点锚点 volatile int i = MAX_VALUE;  而(i--> 0);  出现这种情况://上述问题所在  __delay_cycles(NUMBER_OF_CYCLES); 补救 利用其中一种MSP430低功耗模式,并使用MSP430器件中的一个定时器模块在一段时间后唤醒。 代码示例  // ********* ******************************  // MSP430G2xx3演示 -  Timer_A,切换P1.0,CCR0续。模式ISR,DCO SMCLK  //  //描述:使用软件和TA_0 ISR切换P1.0。切换每一个  // 50000个SMCLK周期。 SMCLK为TACLK提供时钟源。  //在TA_0 ISR期间,切换P1.0并添加50000个时钟周期  // CCR0每50000个周期触发TA_0 ISR。 CPU通常是关闭的  //仅在TA_ISR期间使用。  // ACLK = n / a,MCLK = SMCLK = TACLK =默认DCO  //  // MSP430G2xx3  // ---------------  // / | \ | XIN |  -  // | | |  //  -  | RST XOUT |  -  // | |  // | P1.0 |  - > LED  //  // D. Dang  #include <msp430g2553.h>  void main(void)  {    WDTCTL = WDTPW + WDTHOLD; //停止WDT    P1DIR | = 0x01; // P1.0输出    CCTL0 = CCIE; //启用CCR0中断    CCR0 = 50000;    TACTL = TASSEL_2 + MC_2; // SMCLK,contmode      _BIS_SR(LPM0_bits + GIE); //输入LPM0 w / interrupt  }    //定时器A0中断服务程序  #pragma vector = TIMER0_A0_VECTOR  __interrupt void Timer_A(void)  {    P1OUT ^ = 0x01; //切换P1.0    CCR0 + = 50000; //将偏移添加到CCR0  } 锚点锚点具体代码现在搞不太懂,但是大体上两种解决方法,第一用delay函数实现用时钟定时,第二个就是用中断进入其他的例如AM退出低功耗模式,然后就可以调用cpu来实现循环。 应该是这样,现在第一次学真的搞不来这些代码,只能这样了。

  • 发表了主题帖: MSP430中断的一个细节问题

    关于中断标志:   从SPI发送一字节数据: void SPI_Set_SD_Byte(unsigned char txData) { UCB0TXBUF = txData; // 写入发送缓冲区          while ((UCB0IFG & UCTXIFG) == 0); // 等待发送完毕 } 分析:以9600bps 发送一字节 1ms估算,而以12MHz时钟执行(UCB0TXBUF = txData;)需要时间大概1us, 因此可怕的事情发生了,要等待发送完毕需要浪费3999个CPU周期去查询。如果等待过程换成休眠多好啊! 看下面程序: void SPI_Set_SD_Byte(unsigned char txData) { UCB0TXBUF = txData; // 写入发送缓冲区        LPM3; } #pragma vector=USCI_B0_VECTOR    __interrupt void USCI_B0_ISR(void) {   //order interrupt service   switch (__even_in_range (UCB0IV,8))   {         case 0: break;         case 2: break; case 8: while (!(UCB0IFG&UCTXIFG)); break;         LPM3_EXIT;   } 巧妙地事情发生了,你CPU先歇着,让我SPI单独工作。 但系统中开启仅SPI发送中断时,上面是OK的,可问题来了,只发送不接受吗?有时候SPI通信未必 只有一个外设,为了实现低功耗,常常会唤醒低功耗在中断。   你怎能保证其他终端唤醒CPU时,SPI已发送完毕呢? 本文的重点来了,全局通信变量标志位是一把利剑。 void SPI_Set_SD_Byte(unsigned char txData) { UCB0TXBUF = txData; // 写入发送缓冲区        SPI_TxFlag_sd = 0;// 清除全局标志位         while (SPI_TxFlag_sd == 0 ) // 发送过程中CPU才唤醒         { LPM3;         } } __interrupt void USCI_B0_ISR(void) {   //order interrupt service   switch (__even_in_range (UCB0IV,8))   {         case 0: break;         case 2: break; case 8: SPI_TxFlag_sd = 1;      LPM3_EXIT;      break;       } 分析:任何中断都可能把CPU唤醒,但是只有SPI发送完毕后,SPI_TxFlag_sd 才置1 。

  • 回复了主题帖: 怎样实现TI MSP430单片机低功耗?

    430单片机的低功耗实现方式可以通过软件编程来实现,一般情况下根据需要打开关闭一些模块,减少功耗,正常时让单片机进入低功耗模式,当需要采集数据或有中断来临时唤醒。

  • 发表了主题帖: 怎样实现TI MSP430单片机低功耗?

    430单片机的低功耗实现方式可以通过软件编bai程来实现。   为了du使MSP430最大限度的达zhi到低功耗,对于MSP430未使用的GPIO而言,应该将其设置为输出;或者是设置为输入,但是将管脚的电平固定,可以通过外部电路将管脚连接至Vcc或者GND,也可使能内部上下拉电阻,将管脚电平固定。   对于MSP430而言,大部分情况下,测量到的功耗与datasheet不符均是由对MSP430未使用的GPIO处理不当引起的。默认情况下,MSP430的GPIO是作为输入的,其等效电路如下图所示,为推挽模式:   当GPIO管脚配置为输入管脚且外部电平处于浮动状态时(0<Vin<Vcc),那么内部的MOSFETs管的导通电流本身就处于一个不稳定的值,会导致整体功耗的升高,示意图见上图右半边。另外过高或过低的温度更会加剧这种不稳定,且当供电电压升高时,本身MOSFETs管的导通电流也会变大。故在高压和低温双重作用下,就会出现功耗攀升现象。

  • 发表了主题帖: MSP430硬件I2C使用方法——以BH1710和AT24C02为例

    硬件的I2C控制器终于调出来了,这些天一直在钻死胡同,其实最好的参考资料还是TI官方提供的。代码参考了MSP430的User’s Guide和Application Note,下面提供IAR工程并做简要解释: 采用的芯片:MSP430F1611(USART0 Master方式) 设备地址:BH1710(写地址0x46,读地址0x47),AT24C02(写地址0xA0,读地址0xA1) 工程文件:(采取模块化方法,只需添加I2C文件并修改相应的器件模块即可) 接口电路:   一般情况下,大家在调试I2C设备时会首先考虑采用IO口模拟I2C总线的方法,这样的方法思路简单,只需要给出正确的时序即可。但是这样也有意想不到的问题,比如时序的严格性:同样的时序,在BH1710上就能跑通而AT24C02上就时好时坏,读数据正确而写数据有问题,且十有八九都无法写入。也就是说,不同器件对于时序的要求是有差别的,这样即使编写了通用的模拟程序,也会偶尔出些莫名其妙的问题。 于是我开始鼓捣硬件的I2C,MSP430x15x、MSP430x16x系列的USART带有I2C模式,结构如下: 可以看出,I2C可以通过I2CSSELx位选择时钟输入方式,在完成初始化设置后,通过I2CDRW(Byte方式下用I2CDRB表示)来读写数据,下面是一个I2C初始化过程: 初始化过程的大致顺序为将USART设置为I2C模式,配置I2C工作方式、地址、时钟源和分频,启动I2C控制器。这里需要注意的是,I2CSA中填入的是7位地址,即如果设备的写入地址为0xA0,需要令I2CSA = (0xA0 >> 1),即0x50。 SCL的频率则由I2CPSC、I2CSCLH、I2CSCLL共同决定。I2CPSC为预分频,I2CPSC=0时为一分频,I2CPSC=1时为二分频,最高只支持4分频。I2CSCLH和I2CSCLL分别表示SCL高电平和低电平的持续时间,实际时间TH= (I2CPSC +1) x (I2CSCLH + 2),需要什么频率可以自己算,同时也可以为函数增加一个freq参数,在初始化的时候设置频率。请注意根据手册上的说明,I2CIN输入的时钟源频率至少要等于10*SCL* I2CPSC分频数,至于不这么干会怎样,大家可以试试呀。 void I2C_Init(unsigned char slaveAddress) {   I2C_PORT_SEL |= SDA_PIN + SCL_PIN;        //设置引脚,用作USART接口   I2C_PORT_DIR &= ~(SDA_PIN + SCL_PIN);     U0CTL |= I2C+SYNC;                        //USART0配置为I2C模式   U0CTL &= ~I2CEN;                          //配置I2C前先关闭I2C控制器                                             //这里采用默认配置,7位地址,无DMA,无反馈   I2CTCTL = I2CTRX+I2CSSEL_2;               //byte模式,repeat模式,I2C时钟源为SMCLK   I2CSA = slaveAddress;                     //设置从设备地址     I2COA = 0xAA;                             //本机地址,这个目前用不到     I2CPSC = 0x01;                            //I2C时钟 = SMCLK/2 = 2MHz   I2CSCLH = 0x18;                           //SCL高电平周期 = 20*I2C clock   I2CSCLL = 0x18;                           //SCL低电平周期  = 20*I2C clock                                             //I2C_SCL频率 = 2MHz/20 =100KHz   U0CTL |= I2CEN;                           //开启I2C控制器     if (I2CDCTL&I2CBUSY)                      //检查I2C模块是否空闲,这里应该是检测时钟正确性吧?   {                                             I2C_PORT_SEL &= ~SCL_PIN;               //将SCL设置为IO输出模式并手动置0     I2C_PORT_OUT &= ~SCL_PIN;                   I2C_PORT_DIR |= SCL_PIN;                    I2C_PORT_SEL |= SDA_PIN + SCL_PIN;      //重新设置引脚为I2C模式   }; }   发送数据以BH1710写入指令函数为例,向I2C从设备写入1字节数据,格式及代码如下: Start SlaveAddress W ACK Data ACK Stop   void BH_WriteCmd(unsigned char Cmd) {   while (I2CDCTL&I2CBUSY);                                                    I2CBufferArray[0] = Cmd;   PtrTransmit = 0;                             I2C_WriteMod();   I2CNDAT = 1;                                                                          I2CTCTL |= I2CSTT;                                                                   __bis_SR_register(LPM0_bits + GIE);         I2CTCTL |= I2CSTP;                          while(I2CTCTL & I2CSTP);                } 其中I2CNDAT用于指定发送数据的字节数,I2CSTT位设定开始发送, I2CSTP位设定发送结束。在这里,发送函数只是将数据填入缓存中,实际的发送过程在__interrupt void ISR_I2C(void) 中断函数中完成,而在等待发送中断的过程中,系统进入LPM0休眠,整个过程为阻塞式。   读取函数与发送函数类似,依然已BH1710为例: unsigned int BH_Resualt(void) {   unsigned char byteHight,byteLow;   while (I2CDCTL&I2CBUSY);                  //等待I2C模块空闲     I2C_ReadMod();   I2CNDAT = 2;                              //读取2字节   I2CTCTL |= I2CSTT;                        //发送Start开始接收     __bis_SR_register(LPM0_bits + GIE);       //进入休眠等待   byteHight = I2CBuffer;  //高位数据   __bis_SR_register(LPM0_bits + GIE);   byteLow = I2CBuffer;    //低位数据     I2CTCTL |= I2CSTP;                        //发送Stop结束接收   while(I2CTCTL & I2CSTP);                  //等待Stop发送完毕     return ((((unsigned int)byteHight)<<8)+byteLow);//合成数据 } 需要注意的是,BH1710一次返回两个字节数据,需令I2CNDAT = 2,同时在读完一次缓存后再读取下一个。 对于AT24C02,读取方式有任意地址和当前地址读取的差别,可以参见工程代码。 最后是中断函数: #pragma vector=USART0TX_VECTOR __interrupt void ISR_I2C(void) {   switch (__even_in_range(I2CIV, I2CIV_STT))   {      case I2CIV_RXRDY:   //接收就绪 (RXRDYIFG)       I2CBuffer = I2CDRB;                   //读取数据,跳出休眠       __bic_SR_register_on_exit(LPM0_bits);       break;     case I2CIV_TXRDY:   //发送就绪 (TXRDYIFG)       while(!(I2CDCTL & I2CTXUDF));         //等待上一个数据发送完毕       I2CDRB = I2CBufferArray[PtrTransmit]; //发送Buff中的数据       PtrTransmit--;       if (PtrTransmit < 0)                  //PtrTransmit为发送数据个数的自减计数器,减完表示发送结束       {         I2CIE &= ~TXRDYIE;                  //最后清标志位         I2CIFG &= ~TXRDYIFG;                        __bic_SR_register_on_exit(LPM0_bits);       }       break;   } } I2C的中断变量就是串口发送中断USART0TX_VECTOR,这里只用到了RXRDY 和TXRDY,其他的中断标志位判断已包含在工程文件里,需要时可添加相应代码。这里的接收缓存I2CBuffer只能存储一个字节数据,接收多个字节时需要多次接收,有大量数据接收需要的童鞋可以改成数组的形式,操作方法同I2CBufferArray[]。   参考:Interfacing an EEPROM via I2C Using the MSP430       MSP430x1xx User's Guide

  • 2020-08-02
  • 发表了主题帖: TMS320F28335-CAN模块例程解释

    CAN(Controller Area Network)特点:所有单元可以同时发送消息,发送高优先级ID消息的单元。CAN总线最大的优点是其高效性和可靠性,理论上总线可挂载的单元总数是没有限制的,实际上可连接的单元数受总线上的时间延迟及电气负载的限制。 DSP中内置了CAN协议内核CPK,有32个可配置为接收或发送的邮箱。eCAN模式下,邮箱31具有最高的优先级。 简单解释一下TI提供的例程: 1. ECanaShadow的作用:ECanaRegs不支持位操作,TI的例程中将ECanaRegs赋给ECanaShadow,对影子寄存器进行位操作,提高代码的可读性。 2.ECanaRegs.CANTRS置位后开始发送数据,发送成功后对应的ECanaRegs.CANTAn会置位,向其写1进行复位,继续发送。 3.TI的例程ECANA_to_B中只配置了发送邮箱,要想实现CANA发送,CANB接收需要配置一个接收邮箱。ID与发送邮箱相同,注意在ECan.c中选择自己板子上对应的CAN引脚。 4.ECan接收CAN_USB发送器的信息,通过ECanasShadow.CANRMP.bit.RMPn的值来判断是否接收到消息。当RMPn为1时接收到消息,将其写1复位后继续接收。 5.ECan接收中断的配置:ECanaShadow.CANGIM.bit.I0EN=1、ECanaShadow.CANMIM.bit.MIMn=1。在中断函数里对RMPn写1复位,清除PIEACK的中断标志位。 总结:TI官方提供的ECan.c中已经将ECANA和ECANB都配置好了,我们只需要在接收和发送时对相应的RMPn(接收)和TAn(发送)进行软件复位即可连续接收发送。 PS:与CAN_USB转换器联调时,要注意接线正确,转换器的波特率要与程序配置的一致。

  • 发表了主题帖: 有关CAN通信内容

    通信——结合书本,有一下内容: can通信的数字逻辑,隐性质电平1,显性电平0 can通信的帧分为数据帧、远程帧、错误帧和过载帧。 can的数据帧有帧起始、仲裁场、控制场、数据场、CRC场和帧结尾。 can的远程帧和数据帧的区别是RTR位。 错误帧和过载帧有特定的数据格式。 can错误及其处理方法。 can初始方法——配置标准模式、配置工作模式,等待配置,配置模式有效,改变使能,配置标准模式、等待标准模式配置,配置完成。(建立影子寄存器,保证读取为32位的数据) 时间配置。 发送接收子程序。 过载处理、远程处理等。 中断应用,掉电处理。

  • 发表了主题帖: 图像算法移植的DSP需要做哪些工作

    需要把已经写好的算法,移植到你的DSP开发板上并很好的跑起来,需要做哪些工作呢? 下面我分两部分来讲,第一分部是移植,第二部分为算法优化 移植: 1)如果你的算法是基本opencv这样的基本上开发的,你需要脱离opencv的环境。 2)如果你的算法是C++语言,请你改成标准的C语言。虽然DSP的开发环境是支持C++的,但是不建议你这么做。 3)修改你算法的内存分配,尽量内存一次分配好,DSP在算法不断的申请和释放时会有隐患。优先使用静态数组,会减轻很多工作量。 4)在CCS下建立工程,来调试你的算法,内存分配函数需要使用TI提供的函数。如果你的算法能够长期稳定的运行,那么恭喜你,你的算法移植就完成了。 优化: 算法优化,需要你能懂算法,也懂DSP。如果你只会写DSP程序,而不会算法,这对整个产品来说,是不能达到最优的。有些公司怕算法泄密,给优化人员一段或几段程序让其优化。我觉得这样做是很不合理的。除非你自己能控制大局,精通优化,这样才可行。   1)你需要对算法原理做一个深刻苦的理解,阅读相关的文章。 2)对你拿到的算法做全方位的熟悉。 3)做好上面的准备工作后,你要对算法的结构做重新的整理。依据DSP的特点,比如内存的分布。算法结构调整完成后,你的算法在DSP上速度应该有一个明显的提高了。 4)结构调整完成后,找到算法中比较费时的部分。确定我们需要优化的重点,这部分内容多是每张图像都要处理一次或多次的部分。对于算法启动时初始化部分的内容,一般不需要优化。 5)确定优化内容后,你首先考虑从语言结构上去做优化,这个时候应该还是C语言的。我不建议大家用TI提供的在C语言中使用优化嵌入的C库函数。 6)你把需要优化的函数改写为线性汇编或汇编函数。不断的调整软件流水,提高速率。   这个整个移植优化的工作就基本上做完了,其实实际工作中,移植优化的工作量往往会比较大,要不断的反复,找更好的方法。移植优化跟算法开发一样,是个细致的活。需要静下心来,仔细研究

  • 发表了主题帖: DSP产品研发流程步骤

    1.开发环境CCS(CodeCo   mposerStudio)是TI公司开发的一个完整的DSP集成开发环境。由于TI的DSP使用非常广泛,使得CCS也就成为使用最为广泛的DSP开发软件之一。现在,所有TI公司的DSP都可以在该环境里进行开发,可实现全空间透明仿真,不占用用户任何资源,软件配有汇编/链接、C编译器、C源码调试器等。不同的系统有不同版本的CCS开发环境,TMS320F28l2的集成开发环境是CCS2000。在购买开发板时都会免费赠送CCS开发软件,另外也可以在TI的网站上免费下载该软件,开发环境的安装使用一般在DSP开发板的使用说明书中有详尽的叙述,在此不做赞述。     2.编程语言CCS开发环境支持两种语言:汇编语言和C语言。TI的每个DSP系列都有对应的一套汇编指令,如果采用汇编语言编程,需要熟悉这些指令,难度和效率可想而知。现在TI的工程师在不断改进CCS的C程序优化编译器,目前C优化的效率可达到手工汇编的90%甚至更高。当然有的时候如果计算能力和内存资源是瓶颈,ASM还是有优势,比如G.729编解码。但是针对一般的应用开发,C语言是最好的选择,只要有一定的C语言的基础,就完全可以进行DSP的开发编程。   应用实例及开发流程   1.实例介绍400Hz的逆变电源的控制部分实现的主要功能有:(1)AD转换,(2)SPWM生成,(3)与显示单片机的串口通信,(4)与其他并联电源的CAN总线通信;(5)捕捉同步信号。妥实现以上这些功能,显然普通的单片机是无法完成的,因此我们选择了专门用作控制的数字信号处理器TMS320F2812。在此仪对TMS320F28l2生成SPWM波的开发过程作详细介绍。   PWM(PulseWidthModulation)控制就是对脉冲的宽度进行调制的技术,即通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形。   SPWM波形(SinuSOIdalPWM)就是脉冲的宽度按正弦规律变化而和正弦波等效的PWM波形,在逆变电路中的应用最为广泛。在此例中SPWM的功能是给三相逆变电路的6个IGBT(绝缘栅双极晶体管)提供触发脉冲,从而使直流电逆变为400Hz的正弦交流电。   2.开发流程(1)编写软件SPWM的生成主要是应用TMS320F28l2的事件管理器模块(EVA/B),所以编写程序前要做的主要工作就是了解熟悉这一模块的结构和工作原理,至于其他用不到的模块可暂时不作了解。程序编写的第一步就是要对用到的模块的各种寄存器进行设置,第二步就是算法的设计编写。   本文末尾是笔者编写的已经通过编译的一段生成SPWM(正弦脉宽调制波)的主程序。   (2)调试程序编写完程序后,就要在仿真环境下进行调试,先编译再运行,通过示波器可以直接观察DSP引脚上输出的SPWM波形,直到与要求的波形相符为止。   (3)烧写程序在仿真环境下调试好程序后,需要把程序烧写到DSP的片上FLASH存储器中。烧写时必须先安装专门的烧写软件,安装后就可以直接在CCS环境下操作烧写。烧写完成后就可以脱离仿真器,开发板就可以上电独立运行,并和其他的外围电路相连而实现它的功能。   习方法知参考资源一、习方法初学DSP常常会感觉到技术文档太多,无从下手。根据我的自学经历,这时最应该弄明白的就是DSP芯片的内部硬件工作原理,如果有微机原理和单片机基础的话,这应该是很容易掌握的,如果没有这方面的基础,建议先去找一本微机原理的书看,看明白后再来看DSP的原理。另外,DSP的外设模块有很多,这时没有必要都去了解,只是了解你所用到的模块就可以了。   了解了DSP的工作原理之后,就要去看关于软件开发环境的书,包括软件的安装和使用。然后就找几个完整的工程(购买开发板时都会赠送各模块的完整工程)来看,在似懂非懂的大体了解了一个完整工程的创建及结构后,就可以开始分析和你所用到的模块相关的程序。现在有大量现成的例程和算法可以参考,切忌自己闷头摸索,一定要去找相关的程序来参考,这会起到事半功倍的效果。

  • 发表了主题帖: DM8148从DSP侧发送Frames流到A8侧程序配置

    最近在调试DM8148,根据需求需要将摄像头获取的数据送入DSP进行图像处理后再送入A8进行其他处理(网络发送等),在调试的过程中一直遇到数据从DSP侧发送到A8时,程序只能成功执行几次,然后A8侧的FramesInLink就获取不到数据,仔细阅读官方的例程后,总算是调通了,现在把过程记录下来。 第一次写,有不当或者错误的地方欢迎指出。 将Frames或者Bits数据流从BIOS侧发送到Linux侧时,除了正常的配置之外,还需要额外编写Linux侧中Frames/BitsIn的回调函数,并在回调函数中调用release释放被占用的ListMP资源,否则程序正常运行几次后便会因为队列/链表资源耗尽导致处理器之间的通信失败,现象是Linux能收到NEW_DATA_CMD命令,但是FramesTskMain/BitsTskMain程序中能够获得的有效帧是0(打开SYSTEM_DEBUG_IPC_RT宏后会在串口打印如下信息) 通信失败时串口的打印信息 这里以DSPFramesOut->HostFramesIn为例说明(注意如果是Vpss中只有一路Frames流或者Video中只有一路Bits流发送到Host,则只需要配置gVcamModuleContext.ipcFramesOutVpssToHostId和gVencModuleContext.ipcBitsOutRTOSId这两个参数就可以在配置Prm参数的时候直接使用MCFW库中提供的回调函(这两个可以参考multich_capturedisplay.c和multich_encode_decode.c中相关的参数配置),而不用手动编写回调函数) 由于MCFW库中并没有提供从DSP发送Frames/Bits时Linux侧的配置,因此如果需要完成从DSP发送Frames/Bits到A8侧,需要手动添加回调函数,并在回调函数中读取传过来的Frames/Bits数据。这里以Frames流从DSP发送到A8实例。 首先定义一个全局变量用于记录A8侧用来接收DSP发送来的数据的LinkID。 UInt32 gFramesDsp2HostId; 然后是两个Link的创建参数配置         /*DSP Frames out to host*/         ipcFramesOutDspPrm.baseCreateParams.inQueParams.prevLinkId = ipcFramesInDspId;//helloWorldID;         ipcFramesOutDspPrm.baseCreateParams.inQueParams.prevLinkQueId = 0;         ipcFramesOutDspPrm.baseCreateParams.numOutQue = 1;         ipcFramesOutDspPrm.baseCreateParams.outQueParams[0].nextLink = ipcFramesInHostId0;         ipcFramesOutDspPrm.baseCreateParams.noNotifyMode = TRUE;         ipcFramesOutDspPrm.baseCreateParams.notifyPrevLink = TRUE;         ipcFramesOutDspPrm.baseCreateParams.notifyNextLink = FALSE;         ipcFramesOutDspPrm.baseCreateParams.inputFrameRate = 30;         ipcFramesOutDspPrm.baseCreateParams.outputFrameRate = 30;         /*host Frames in from DSP*/         ipcFramesInHostPrm0.baseCreateParams.inputFrameRate = 30;         ipcFramesInHostPrm0.baseCreateParams.inQueParams.prevLinkId = ipcFramesOutDspId;         ipcFramesInHostPrm0.baseCreateParams.inQueParams.prevLinkQueId = 0;         ipcFramesInHostPrm0.baseCreateParams.outQueParams[0].nextLink = SYSTEM_LINK_ID_INVALID;         ipcFramesInHostPrm0.baseCreateParams.notifyNextLink = FALSE;         ipcFramesInHostPrm0.baseCreateParams.notifyPrevLink = FALSE;         ipcFramesInHostPrm0.baseCreateParams.noNotifyMode = TRUE;         ipcFramesInHostPrm0.exportOnlyPhyAddr = TRUE;         ipcFramesInHostPrm0.cbCtx = NULL;         ipcFramesInHostPrm0.cbFxn = i_ipcFramesHostCb; ipcFramesInHostPrm0.cbFxn表示A8侧收到数据后调用的回调函数指针,ipcFramesInHostPrm0.cbCtx为传入ipcFramesInHostPrm0.cbFxn的形参,这里使用gFrames2HostID来记录linkID,没有参数需要传向ipcFramesInHostPrm0.cbFxn,所以这里设置为NULL。 然后是回调函数Void i_ipcFramesHostCb(Ptr cbCtx)。 /*DSP 帧到host的回调函数,其中cbCtx为NULL*/ Void i_ipcFramesHostCb(Ptr cbCtx) {     UInt32 status = 0;     VIDEO_FRAMEBUF_LIST_S bufList;     OSA_printf("----------ipc Frames get from DSP Host link ID is %X-------------\n", gFramesDsp2HostId);     #if 1     VDsp_getFullVideoFrames(gFramesDsp2HostId, &bufList, 0);     OSA_printf("----------host get frames in ListMP-------------\n");     if (bufList.numFrames){             status = VDsp_putEmptyVideoFrames(gFramesDsp2HostId, &bufList);             OSA_assert(0 == status);             OSA_printf("----------Host release frames to MCFW-------------\n");     }     #endif } 关于这个函数的实现可以参考ti_vcap.c中static Void * App_ipcFramesSendRecvFxn(Void * prm)函数,这里实现与官方的稍有差异,官方库中App_ipcFramesSendRecvFxn为一个在初始化时候创建的线程,该线程创建完成后,便进入等待状态,回调函数仅向App_ipcFramesSendRecvFxn发送一个信号量,用来启动线程,线程启动后,进行处理相关操作。 接下来是VDsp_putEmptyVideoFrames和VDsp_getFullVideoFrames的实现。这两个函数的实现同样是参考ti_vcap.c中Vcam_getFullVideoFrames和Vcam_getFullVideoFrames的实现。 /*释放帧*/ Int32 VDsp_putEmptyVideoFrames(UInt32 linkID, VIDEO_FRAMEBUF_LIST_S *pFrameBufList) {     VIDEO_FRAMEBUF_S *pSrcBuf;     VIDFrame_Buf     *pDstBuf;     VIDFrame_BufList  vidBufList;     UInt32 i;     Int status = 0;     vidBufList.numFrames = pFrameBufList->numFrames;     for (i = 0; i < vidBufList.numFrames; i++)     {         pSrcBuf = &pFrameBufList->frames[i];         pDstBuf = &vidBufList.frames[i];         Vcam_copyVidFrameInfoMcFw2Link(pDstBuf,pSrcBuf);     }     if (vidBufList.numFrames)     {         status =         IpcFramesInLink_putEmptyVideoFrames(linkID,                                             &vidBufList);     }     return 0; } /*Host 获取从DSP传过来的帧*/ Int32 VDsp_getFullVideoFrames(UInt32 linkID,                               VIDEO_FRAMEBUF_LIST_S *pFrameBufList, UInt32 timeout) {     VIDFrame_BufList  vidBufList;     VIDFrame_Buf     *pInBuf;     VIDEO_FRAMEBUF_S *pOutBuf;     UInt32 i;     pFrameBufList->numFrames = 0;     vidBufList.numFrames = 0;     IpcFramesInLink_getFullVideoFrames(linkID, &vidBufList);     pFrameBufList->numFrames = vidBufList.numFrames;     for (i = 0; i < vidBufList.numFrames; i++)     {         pOutBuf = &pFrameBufList->frames[i];         pInBuf = &vidBufList.frames[i];         Vcam_copyVidFrameInfoLink2McFw(pOutBuf,pInBuf);     }     return 0; } 配置完成后,上电通过串口可以看到如下连续的打印信息,表示配置成功,A8侧读取到DSP发送的Frames流 配置成功后串口打印

  • 2020-08-01
  • 发表了主题帖: TI 的高效集成电源选择和参考设计简介

    德州仪器的高效集成电源     TI广泛的电源管理IC产品组合可支持NXP处理器和Xilinx FPGAs的需求。从我们完整的参考设计(带有文档的硬件和软件)中可以看出,TI PMIC可配置为支持非TI处理器供电。 这些参考设计基于用户可编程的PMIC(如TPS6521815),使用户能够对非易失性EEPROM存储器进行编程,以产生所需的电压、排序和其他特殊功能,从而简化设计并缩短上市时间。同一个设备可以多次编程,为不同系统中的各种处理器或FPGA供电,而不需要更改印刷电路板,因此可以最小化电路板上的组件数量。 TI PMIC还提供了额外的功能,如电源故障检测(不受控制断电的早期检测)、断电有源放电和扩展温度支持(-40至105⁰C)。 可用于NXP处理器的TI特色资源: 使用TI的TPS6521815 PMIC为i.MX 6和i.MX 7处理器提供电源            使用TPS6521815 PMIC为 NXP i.MX 6Solo, 6DualLite供电            使用TPS6521815 PMIC为NXP i.MX 7处理器供电 使用TI的TPS65218D0和LP87332D PMIC为i.MX 8M Mini和Nano处理器提供电源            使用TI PMIC为NXP i.MX 8M Mini和Nano供电 TI针对NXP i.MX 8M微型处理器推出的TIDA-050038集成电源参考设计            可从第三方处购买SOM电路板快速原型 – VVDN TI针对NXP i.MX 7D处理器推出的TIDA-050034集成电源参考设计 可从第三方处购买SOM电路板快速原型 – VVDN 可用于Xilinx处理器的TI特色资源: TI用于Xilinx® Zynq® UltraScale+™ MPSoC应用的电源参考设计 TI用于Xilinx Artix®-7、Spartan®-7和Zynq®-7000 FPGAs的集成电源参考设计 TI用于Xilinx® Zynq® UltraScale+™ ZU2CG–ZU5EV MPSoCs的集成电源参考设计

统计信息

已有1332人来访过

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

留言

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


博浩元电子 2018-10-25
不错,干货
查看全部