这代人的热情-捣鼓一块MSP430FR2533
在前面一篇文章中这代人的热情-haman/kardon哈曼卡顿 R1 音箱腔体,提到一块MSP430的成品电路板,其中带了几颗WS2812。单独为了一块板子捣鼓太麻烦了,如果只是为了RGB灯的话,可以用Arduino或者ESP8266,使用kitesurfer1404/WS2812FX,就能很容易的控制。
- SBWTDIO(RST)
- SBWTCK(RST)
- 3V3(RST)
- GND(RST)
- TXD(P1.4)
- 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 可以穿透厚玻璃、塑料外壳、金属和木材,在恶劣的环境(包括潮湿、油腻和脏污环境)中工作。
下面的代码是群友提供的:
#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
}
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。