在前面一篇文章中这代人的热情-haman/kardon哈曼卡顿 R1 音箱腔体,提到一块MSP430的成品电路板,其中带了几颗WS2812。单独为了一块板子捣鼓太麻烦了,如果只是为了RGB灯的话,可以用Arduino或者ESP8266,使用kitesurfer1404/WS2812FX,就能很容易的控制。

背面

  1. SBWTDIO(RST)
  2. SBWTCK(RST)
  3. 3V3(RST)
  4. GND(RST)
  5. TXD(P1.4)
  6. RXD(P1.5)

R83上接5V

正面

如果要用IAR开发,那得使用IAR embedded Workbench for MSP430。依旧使用JTAG、SBW、BSL接口。

  • msp430是用的ti的自有内核,RISC(精简指令集)
  • msp432是用的cortex-M4f内核

手册可以看这里:MSP430FR4xx and MSP430FR2xx family user's guide (Rev. I)

MSP430FR263x 和 MSP430FR253x 是用于电容式触控检测的超低功耗 MSP430™ 微控制器,采用 CapTIvate™ 触控技术,适用于按钮、滑块、滚轮及接近传感 应用提供了出色的功能性与安全性。采用 CapTIvate 技术的 MSP430 MCU 提供市面上最高集成度和自主性的电容式触控解决方案,具有高可靠性和抗噪能力以及最低功耗。TI 的电容式触控技术支持在同一设计方案中同时使用自电容式和互电容式电极,最大限度地提高了灵活性。采用 CapTIvate 技术的 MSP430 MCU 可以穿透厚玻璃、塑料外壳、金属和木材,在恶劣的环境(包括潮湿、油腻和脏污环境)中工作。

20200113204410.webp

20200113205043.png

20200113204956.webp

20200113205240.webp

下面的代码是群友提供的:

#include <msp430.h>

void Software_Trim(void);                       // Software Trim to get the best DCOFTRIM value
void System_Clock_Config(void);                   // Configure MCLK for 8MHz sourced from DCO.
void eUSCI_A1_Config(void);                     //SPI mode
void WS2812_Write(void);
void WS2812_Set_Color(unsigned char num, unsigned char RGB_R, unsigned char RGB_G, unsigned char RGB_B);
void WS2812_Init(void);

#define MCLK_FREQ_MHZ 8                     // MCLK = 8MHz

unsigned char *p;
unsigned char TXBuffer[312];
unsigned int SPICounter;

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;                 // Stop WDT
    System_Clock_Config();
    eUSCI_A1_Config();

    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;

    WS2812_Init();
    WS2812_Set_Color(0, 255, 0, 0);
    WS2812_Set_Color(1, 192, 64, 0);
    WS2812_Set_Color(2, 128, 128, 0);
    WS2812_Set_Color(3, 64, 192, 0);
    WS2812_Set_Color(4, 0, 255, 0);
    WS2812_Set_Color(5, 0, 192, 64);
    WS2812_Set_Color(6, 0, 128, 128);
    WS2812_Set_Color(7, 0, 64, 192);
    WS2812_Set_Color(8, 0, 0, 255);
    WS2812_Set_Color(9, 64, 0, 192);
    WS2812_Set_Color(10, 128, 0, 128);
    WS2812_Set_Color(11, 192, 0, 64);
    WS2812_Set_Color(12, 255, 255, 255);
    WS2812_Write();
    __bis_SR_register(LPM4_bits);
}

void WS2812_Init(void)
{
    unsigned char i, j;
    j = 13;
    p = TXBuffer;
    while(j--)
    {
        i = 8;
        while(i--)
            *p++ = 0x70;
        i = 8;
        while(i--)
            *p++ = 0x70;
        i = 8;
        while(i--)
            *p++ = 0x70;
    }
    WS2812_Write();
}

void WS2812_Set_Color(unsigned char num, unsigned char RGB_R, unsigned char RGB_G, unsigned char RGB_B)
{
    unsigned char i;
    if(num < 13)
    {
        p = TXBuffer + 24 * num;
        i = 8;
        while(i--)
        {
            if(RGB_R & BIT7)
            {
                *p++ = 0x7C;
            }
            else
            {
                *p++ = 0x70;
            }
            RGB_R <<= 1;
        }
        i = 8;
        while(i--)
        {
            if(RGB_G & BIT7)
            {
                *p++ = 0x7C;
            }
            else
            {
                *p++ = 0x70;
            }
            RGB_G <<= 1;
        }
        i = 8;
        while(i--)
        {
            if(RGB_B & BIT7)
            {
                *p++ = 0x7C;
            }
            else
            {
                *p++ = 0x70;
            }
            RGB_B <<= 1;
        }
    }
}


void WS2812_Write(void)
{
    p = TXBuffer;
    SPICounter = 312;
    UCA1IE |= UCTXIE;                     // Enable TX interrupt
    UCA1IFG |= UCTXIFG;
    __bis_SR_register(LPM0_bits | GIE);   // enable global interrupts, enter LPM0
    __no_operation();                     // For debug,Remain in LPM0
    __delay_cycles(5000);
}

void eUSCI_A1_Config(void)
{
    P2SEL0 |= BIT6;

    UCA1CTLW0 |= UCSWRST;                     // **Put state machine in reset**
    UCA1CTLW0 |= UCMST|UCSYNC|UCMSB;   // 3-pin, 8-bit SPI master
                                              // Clock polarity high, MSB
    UCA1CTLW0 |= UCSSEL__SMCLK;               // SMCLK
    UCA1BR0 = 0x00;                           // fBitClock = fBRCLK.
    UCA1BR1 = 0;                              //
    UCA1MCTLW = 0;                            // No modulation
    UCA1CTLW0 &= ~UCSWRST;                    // **Initialize USCI state machine**
    UCA1IFG &= ~UCTXIFG;
}


void System_Clock_Config(void)
{
    __bis_SR_register(SCG0);                // disable FLL
    CSCTL3 |= SELREF__REFOCLK;              // Set REFO as FLL reference source
    CSCTL1 = DCOFTRIMEN | DCOFTRIM0 | DCOFTRIM1 | DCORSEL_3;// DCOFTRIM=3, DCO Range = 8MHz
    CSCTL2 = FLLD_0 + 243;                  // DCODIV = 8MHz
    __delay_cycles(3);
    __bic_SR_register(SCG0);                // enable FLL
    Software_Trim();                        // Software Trim to get the best DCOFTRIM value

    CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK; // set default REFO(~32768Hz) as ACLK source, ACLK = 32768Hz
                                            // default DCODIV as MCLK and SMCLK source
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
    switch(__even_in_range(UCA1IV,USCI_SPI_UCTXIFG))
    {
        case USCI_NONE: break;                // Vector 0 - no interrupt
        case USCI_SPI_UCRXIFG: break;
        case USCI_SPI_UCTXIFG:
              if(SPICounter)
              {
                  UCA1TXBUF = *p++;             // Transmit characters
                  SPICounter--;
              }
              else
              {
                  UCA1IE &= ~UCTXIE;
                  __bic_SR_register_on_exit(LPM0_bits);
              }
              break;
        default: break;
    }
}

void Software_Trim()
{
    unsigned int oldDcoTap = 0xffff;
    unsigned int newDcoTap = 0xffff;
    unsigned int newDcoDelta = 0xffff;
    unsigned int bestDcoDelta = 0xffff;
    unsigned int csCtl0Copy = 0;
    unsigned int csCtl1Copy = 0;
    unsigned int csCtl0Read = 0;
    unsigned int csCtl1Read = 0;
    unsigned int dcoFreqTrim = 3;
    unsigned char endLoop = 0;

    do
    {
        CSCTL0 = 0x100;                         // DCO Tap = 256
        do
        {
            CSCTL7 &= ~DCOFFG;                  // Clear DCO fault flag
        }while (CSCTL7 & DCOFFG);               // Test DCO fault flag

        __delay_cycles((unsigned int)3000 * MCLK_FREQ_MHZ);// Wait FLL lock status (FLLUNLOCK) to be stable
                                                           // Suggest to wait 24 cycles of divided FLL reference clock
        while((CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)) && ((CSCTL7 & DCOFFG) == 0));

        csCtl0Read = CSCTL0;                   // Read CSCTL0
        csCtl1Read = CSCTL1;                   // Read CSCTL1

        oldDcoTap = newDcoTap;                 // Record DCOTAP value of last time
        newDcoTap = csCtl0Read & 0x01ff;       // Get DCOTAP value of this time
        dcoFreqTrim = (csCtl1Read & 0x0070)>>4;// Get DCOFTRIM value

        if(newDcoTap < 256)                    // DCOTAP < 256
        {
            newDcoDelta = 256 - newDcoTap;     // Delta value between DCPTAP and 256
            if((oldDcoTap != 0xffff) && (oldDcoTap >= 256)) // DCOTAP cross 256
                endLoop = 1;                   // Stop while loop
            else
            {
                dcoFreqTrim--;
                CSCTL1 = (csCtl1Read & (~(DCOFTRIM0+DCOFTRIM1+DCOFTRIM2))) | (dcoFreqTrim<<4);
            }
        }
        else                                   // DCOTAP >= 256
        {
            newDcoDelta = newDcoTap - 256;     // Delta value between DCPTAP and 256
            if(oldDcoTap < 256)                // DCOTAP cross 256
                endLoop = 1;                   // Stop while loop
            else
            {
                dcoFreqTrim++;
                CSCTL1 = (csCtl1Read & (~(DCOFTRIM0+DCOFTRIM1+DCOFTRIM2))) | (dcoFreqTrim<<4);
            }
        }

        if(newDcoDelta < bestDcoDelta)         // Record DCOTAP closest to 256
        {
            csCtl0Copy = csCtl0Read;
            csCtl1Copy = csCtl1Read;
            bestDcoDelta = newDcoDelta;
        }

    }while(endLoop == 0);                      // Poll until endLoop == 1

    CSCTL0 = csCtl0Copy;                       // Reload locked DCOTAP
    CSCTL1 = csCtl1Copy;                       // Reload locked DCOFTRIM
    while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // Poll until FLL is locked
}