51/AVR单片机技术驿站!  <在线翻译>     便利工具    特色网址   无弹窗、无插件的绿色站点...  英才招聘   学历查询  喜欢>>收藏我站 

当前位置:首页 > 单片机技术文章 > MSP430单片机 > 详细内容
MSP430与MMC/SD卡接口设计[DIY]
发布时间:2009/7/28  阅读次数:3495  字体大小: 【】 【】【
这是一个MSP430与MMC/SD卡接口设计,提供纯源代码。真正DIY设计!
   由Rolf Freitag先生提供。
原文:A self documenting project (C source code) for reading/writing on MMC/SD cards in spi mode and with a hello world LED as output. The code works with many MMC/SD cards but not all; it is beta. The reasons are that some waiting times are not limited in the standard and that the cards are a little outside the standard specifications.
For a release version, which does not cost much and which has a mapping layer for reading/writing 1..512 Bytes starting at any address, you can contact me.
In 2003 TI planned to release an application note to this code but it seems that plan died.
I published the code under a beerware license:
        main.c   mmc.c   mmc.h   led.c   led.h

main.c
/*********************************************************

Program for Communikation of an MSP430F149 and an MMC via SPI in unprotected Mode.
Sytem quartz: 8 MHz, layout: see mmc.h.

Version 0.02 from 11. May 2003

Status: Everything works, but approx. 2 % of all MMC/SDCs do need some longer waiting cycles,
because some times are not limitated in the standards and every card is not strictly standard
conforming; they all do need more waiting cycles as specified in the standards.
*********************************************************/
/*
  * ----------------------------------------------------------------------------
  * "THE BEER-WARE LICENSE" (Revision 43):
  * Rolf Freitag (webmaster at true-random.com) wrote this file.
  * As long as you retain this notice you can do whatever
  * the LGPL (Lesser GNU public License) allows with this stuff.
  * If you think this stuff is worth it, you can send me money via
  * paypal or if we met some day you can buy me a beer in return.
  * ----------------------------------------------------------------------------
  */
#include   <msp430x14x.h>
#include   <string.h>
#include "mmc.h"
#include "led.h"

extern char card_state;

extern char mmc_buffer[512];

char card_state = 0;                                                 // card state: 0: not found, 1 found (init successfull)
unsigned long loop;

void main (void)
{
   volatile unsigned char dco_cnt = 255;

   BCSCTL1 &= ~XT2OFF;                                               // XT2on
   do                                                                            // wait for MCLK from quartz
   {
      IFG1 &= ~OFIFG;                                                   // Clear OSCFault flag
      for (dco_cnt = 0xff; dco_cnt > 0; dco_cnt--); // Time for flag to set
   }
   while ((IFG1 & OFIFG) != 0);                                // OSCFault flag still set?

   WDTCTL = WDTPW + WDTHOLD;                                     // Stop WDT

   BCSCTL1 = 0x07;                                                      // LFXT1: XT2on: LF quartz for MCLK

   BCSCTL2 = SELM1 + SELS;                                         // LFXT2: use HF quartz (XT2)

   DCOCTL = 0xe0;

   P3SEL = 0x00;
   P3DIR = 0xcf;
   P3OUT = 0x0f;

   // Port 4 Function                 Dir       On/Off
   //              4.0-Led red           Out           0 - off    1 - On
   //              4.1-Led green       Out           0 - off    1 - On
   //              4.5-CardDetected    ?            0 - ?       1 - ?
   //              4.6-WriteProtected ?            0 - ?       1 - ?
   // D 7 6 5 4 3 2 1 0
   P4SEL = 0x00;                                                         //    0 0 0 0 0 0 0 0
   P4DIR = 0x03;                                                         //    0 0 0 0 0 0 1 1
   P4OUT = 0x00;

   // Port 5 Function                 Dir           On/Off
   //              5.1-Dout                Out           0 - off      1 - On
   //              5.2-Din                 Inp           0 - off      1 - On
   //              5.3-Clk                 Out           -
   //              5.4-mmcCS              Out           0 - Active 1 - none Active

   P5SEL = 0x00;
   P5DIR = 0xff;
   P5OUT = 0xfe;

   P6SEL = 0x00;
   P6OUT = 0x00;
   P6DIR = 0xff;

   ADC12IE = 0;
   ADC12IFG = 0;

   initLED();
   for (;;)
   {
      // switch on red led to indicate -> insert card

      // #ifdef DeBuG0
      RED_LED_ON();
      GREEN_LED_OFF();
      // Card insert?
      while(P4IN&0x20);
      //switch off both leds
      GREEN_LED_OFF();
      RED_LED_OFF();
      //init mmc card
      if (initMMC() == MMC_SUCCESS)                           // card found
      {
         card_state |= 1;
         GREEN_LED_ON();
         // Read Out Card Type and print it or trace memory
         memset(&mmc_buffer,0,512);
         mmcReadRegister (10, 16);
         mmc_buffer[7]=0;
         // PLease mofify based on your Compiler sim io function
         // debug_printf("Multi Media Card Name: %s",&mmc_buffer[3]);

         // Fill first Block (0) with A
         memset(&mmc_buffer,A,512);                          //set breakpoint and trace mmc_buffer contents
         mmcWriteBlock(0x00);
         // Fill second Block (1)-AbsAddr 512 with B
         memset(&mmc_buffer,B,512);
         mmcWriteBlock(512);

         // Read first Block back to buffer
         memset(&mmc_buffer,0x00,512);
         mmcReadBlock(0x00,512);
         memset(&mmc_buffer,0x00,512);                        //set breakpoint and trace mmc_buffer contents
         mmcReadBlock(512,512);
         memset(&mmc_buffer,0x00,512);                        //set breakpoint and trace mmc_buffer contents
      }

      else
      {
         //Error card not detected or rejected during writing
         // switch red led on
         card_state = 0;                                               // no card
         RED_LED_ON();
      }

      // #endif

   }
   //   return;
}

mmc.h
/*
   mmc.h: Dekcarations for Communikation with the MMC (see mmc.c) in unprotected spi mode.

Pin configuration at MSP430F149:
--------------------------------
   MC                                MC Pin                MMC                                    MMC Pin
   P5.4                             48                      ChipSelect                        1
   P5.1 / SlaveInMasterOut 45                   DataIn                               2
   .                                                             GND                                    3 (0 V)
   .                                                             VDD                                    4 (3.3 V)
   P5.3 UCLK1 / SlaveCLocK 47                   Clock                                5
   .                                                             GND                                    6 (0 V)
   P5.2 / SlaveOutMasterIn 46                   DataOut                             7
   P5.4                                                        CardDetect with pullup
---------------------------------------------------------------------

  Revisions
  Date                 Author                                                        Revision
  11. May 2003                 Rolf Freitag                                              0.02
(2004: corrected MC pin numbers (switched only 45, 46))
*/
/*
  * ----------------------------------------------------------------------------
  * "THE BEER-WARE LICENSE" (Revision 44):
  * Rolf Freitag (webmaster at true-random.com) wrote this file.
  * As long as you retain this notice you can do whatever
  * the LGPL (Lesser GNU public License) allows with this stuff.
  * If you think this stuff is worth it, you can send me money via
  * paypal or if we met some day you can buy me a beer in return.
  * ----------------------------------------------------------------------------
  */
#ifndef _MMCLIB_H
#define _MMCLIB_H

#ifndef TXEPT                                                             // transmitter-empty flag
#define TEXPT 0x01
#endif

// macro defines
#define HIGH(a) ((a>>8)&0xFF)                                  // high byte from word
#define LOW(a) (a&0xFF)                                            // low byte from word

#define CS_LOW()   P5OUT &= ~0x10                             // Card Select
#define CS_HIGH() P5OUT |= 0x10                               // Card Deselect
#define SPI_RXC (IFG2 & URXIFG1)
#define SPI_TXC (IFG2 & UTXIFG1)

#define SPI_RX_COMPLETE (IFG2 & URXIFG1)
#define SPI_TX_READY (IFG2 & UTXIFG1)

#define DUMMY 0xff

// Tokens (nessisary because at nop/idle (and CS active) only 0xff is on the data/command line)
#define MMC_START_DATA_BLOCK_TOKEN      0xfe            // Data token start byte, Start Single Block Read
#define MMC_START_DATA_MULTIPLE_BLOCK_READ   0xfe   // Data token start byte, Start Multiple Block Read
#define MMC_START_DATA_BLOCK_WRITE      0xfe            // Data token start byte, Start Single Block Write
#define MMC_START_DATA_MULTIPLE_BLOCK_WRITE 0xfc   // Data token start byte, Start Multiple Block Write
#define MMC_STOP_DATA_MULTIPLE_BLOCK_WRITE   0xfd   // Data toke stop byte, Stop Multiple Block Write

// an affirmative R1 response (no errors)
#define MMC_R1_RESPONSE           0x00

// this variable will be used to track the current block length
// this allows the block length to be set only when needed
// unsigned long _BlockLength = 0;

// error/success codes
#define MMC_SUCCESS                 0x00
#define MMC_BLOCK_SET_ERROR    0x01
#define MMC_RESPONSE_ERROR      0x02
#define MMC_DATA_TOKEN_ERROR   0x03
#define MMC_INIT_ERROR            0x04
#define MMC_CRC_ERROR              0x10
#define MMC_WRITE_ERROR           0x11
#define MMC_OTHER_ERROR           0x12
#define MMC_TIMEOUT_ERROR       0xFF

// commands: first bit 0 (start bit), second 1 (transmission bit); CMD-number + 0ffsett 0x40
#define MMC_GO_IDLE_STATE    0x40                             //CMD0
#define MMC_SEND_OP_COND   0x41                                //CMD1
#define MMC_READ_CSD      0x49                                    //CMD9
#define MMC_SEND_CID      0x4a                                    //CMD10
#define MMC_STOP_TRANSMISSION    0x4c                      //CMD12
#define MMC_SEND_STATUS    0x4d                                //CMD13
#define MMC_SET_BLOCKLEN   0x50                                //CMD16 Set block length for next read/write
#define MMC_READ_SINGLE_BLOCK    0x51                      //CMD17 Read block from memory
#define MMC_READ_MULTIPLE_BLOCK 0x52                      //CMD18
#define MMC_CMD_WRITEBLOCK   0x54                             //CMD20 Write block to memory
#define MMC_WRITE_BLOCK    0x58                                //CMD25
#define MMC_WRITE_MULTIPLE_BLOCK 0x59                     //CMD??
#define MMC_WRITE_CSD       0x5b                                //CMD27 PROGRAM_CSD
#define MMC_SET_WRITE_PROT   0x5c                             //CMD28
#define MMC_CLR_WRITE_PROT   0x5d                             //CMD29
#define MMC_SEND_WRITE_PROT    0x5e                          //CMD30
#define MMC_TAG_SECTOR_START   0x60                          //CMD32
#define MMC_TAG_SECTOR_END   0x61                             //CMD33
#define MMC_UNTAG_SECTOR   0x62                                //CMD34
#define MMC_TAG_EREASE_GROUP_START 0x63                 //CMD35
#define MMC_TAG_EREASE_GROUP_END 0x64                     //CMD36
#define MMC_UNTAG_EREASE_GROUP   0x65                      //CMD37
#define MMC_EREASE      0x66                                       //CMD38
#define MMC_READ_OCR      0x67                                    //CMD39
#define MMC_CRC_ON_OFF      0x68                                //CMD40

//TI added sub function for top two spi_xxx

// mmc init
char initMMC (void);
// send command to MMC
void mmcSendCmd (const char cmd, unsigned long data, const char crc);
// set MMC block length of count=2^n Byte
char mmcSetBlockLength (const unsigned long);
// read a size Byte big block beginning at the address.
char mmcReadBlock(const unsigned long address, const unsigned long count);
// write a 512 Byte big block beginning at the (aligned) adress
char mmcWriteBlock (const unsigned long address);
// Register arg1 der Laenge arg2 auslesen (into the buffer)
char mmcReadRegister(const char, const unsigned char);
#endif                                                                        /* _MMCLIB_H */

mmc.c
// mmc.c : MultiMediaCard functions: init, read, write ...
// Works also with SC cars. Modes: SPI mode.
//
// Rolf Freitag 5/2003
//
/* See also:
http://www.sandisk.com/pdf/oem/ProdManualSDCardv1.9.pdf Sandisk SD card product manual
http://www.sandisk.com/pdf/oem/ProdManualminiSDv1.1.pdf MiniSD card
http://www.sandisk.com/download/Product%20Manuals/Product%20ManualSDCardv1.7.pdf Older SD card
http://www.compile-it.com/support/crndatasheets/MMC%20ADAPTER.pdf
*/

/*
  * ----------------------------------------------------------------------------
  * "THE BEER-WARE LICENSE" (Revision 44):
  * Rolf Freitag (webmaster at true-random.com) wrote this file.
  * As long as you retain this notice you can do whatever
  * the LGPL (Lesser GNU public License) allows with this stuff.
  * If you think this stuff is worth it, you can send me money via
  * paypal or if we met some day you can buy me a beer in return.
  * ----------------------------------------------------------------------------
  */

// MMC Lib
#ifndef _MMCLIB_C
#define _MMCLIB_C
//---------------------------------------------------------------------
#include "mmc.h"
#include "led.h"

#include   "MSP430x14x.H"
#include   "math.h"
#include   "string.h"

char mmcGetResponse(void);
char mmcGetXXResponse(const char resp);
char mmcCheckBusy(void);

void initSPI (void);
unsigned char spiSendByte(const unsigned char data);

char mmc_buffer[512] =                                              // Buffer for mmc i/o for data and registers
{
   0
};

extern char card_state;                                            // 0 for no card found, 1 for card found (init successfull)

//---------------------------------------------------------------------

// setup usart1 in spi mode
void initSPI (void)
{
   ME2 |= USPIE1;                                                        // Enable USART1 SPI mode
   UTCTL1 = CKPH | SSEL1 | SSEL0 | STC;                   // SMCLK, 3-pin mode, clock idle low, data valid on rising edge, UCLK delayed
   UBR01 = 0x02;                                                         // 0x02: UCLK/2 (4 MHz), works also with 3 and 4
   UBR11 = 0x00;                                                         // -"-
   UMCTL1 = 0x00;                                                        // no modulation
   UCTL1 = CHAR | SYNC | MM;                                     // 8-bit SPI Master **SWRST**
   P5SEL |= 0x0E;                                                        // P5.1-3 SPI option select
   P5DIR |= 0x01;                                                        // P5.0 output direction
   P5OUT = 0xff;
   while (!(IFG2 & UTXIFG1));                                    // USART1 TX buffer ready (empty)?
   // debug_printf("init......SPI");
}


// Initialisieren
char initMMC (void)
{

   //raise SS and MOSI for 80 clock cycles
   //SendByte(0xff) 10 times with SS high
   //RAISE SS
   int i;
   char response=0x01;

   // debug_printf("Start iniMMC......");
   initSPI();
   //initialization sequence on PowerUp
   CS_HIGH();
   for(i=0;i<=9;i++)
      spiSendByte(0xff);
   CS_LOW();
   //Send Command 0 to put MMC in SPI mode
   mmcSendCmd(0x00,0,0x95);
   //Now wait for READY RESPONSE
   if(mmcGetResponse()!=0x01);
   //           debug_printf("no responce");

   while(response==0x01)
   {
      //   debug_printf("Sending Command 1");
      CS_HIGH();
      spiSendByte(0xff);
      CS_LOW();
      mmcSendCmd(0x01,0x00,0xff);
      response=mmcGetResponse();
   }
   CS_HIGH();
   spiSendByte(0xff);
   // debug_printf("MMC INITIALIZED AND SET TO SPI MODE PROPERLY.");
   return MMC_SUCCESS;
}


// Ti added mmc Get Responce
char mmcGetResponse(void)
{
   //Response comes 1-8bytes after command
   //the first bit will be a 0
   //followed by an error code
   //data will be 0xff until response
   int i=0;

   char response;

   while(i<=64)
   {
      response=spiSendByte(0xff);
      if(response==0x00)break;
      if(response==0x01)break;
      i++;
   }
   return response;
}


char mmcGetXXResponse(const char resp)
{
   //Response comes 1-8bytes after command
   //the first bit will be a 0
   //followed by an error code
   //data will be 0xff until response
   int i=0;

   char response;

   while(i<=500)
   {
      response=spiSendByte(0xff);
      if(response==resp)break;
      i++;
   }
   return response;
}


char mmcCheckBusy(void)
{
   //Response comes 1-8bytes after command
   //the first bit will be a 0
   //followed by an error code
   //data will be 0xff until response
   int i=0;

   char response;
   char rvalue;
   while(i<=64)
   {
      response=spiSendByte(0xff);
      response &= 0x1f;
      switch(response)
      {
         case 0x05: rvalue=MMC_SUCCESS;break;
         case 0x0b: return(MMC_CRC_ERROR);
         case 0x0d: return(MMC_WRITE_ERROR);
         default:
             rvalue = MMC_OTHER_ERROR;
             break;
      }
      if(rvalue==MMC_SUCCESS)break;
      i++;
   }
   i=0;
   do
   {
      response=spiSendByte(0xff);
      i++;
   }while(response==0);
   return response;
}


// The card will respond with a standard response token followed by a data
// block suffixed with a 16 bit CRC.

// Ti Modification: long int -> long ; int -> long
char mmcReadBlock(const unsigned long address, const unsigned long count)
{
   unsigned long i = 0;
   char rvalue = MMC_RESPONSE_ERROR;

   // Set the block length to read
   if (mmcSetBlockLength (count) == MMC_SUCCESS)    // block length could be set
   {
      // SS = LOW (on)
      CS_LOW ();
      // send read command MMC_READ_SINGLE_BLOCK=CMD17
      mmcSendCmd (17,address, 0xFF);
      // Send 8 Clock pulses of delay, check if the MMC acknowledged the read block command
      // it will do this by sending an affirmative response
      // in the R1 format (0x00 is no errors)
      if (mmcGetResponse() == 0x00)
      {
         // now look for the data token to signify the start of
         // the data
         if (mmcGetXXResponse(MMC_START_DATA_BLOCK_TOKEN) == MMC_START_DATA_BLOCK_TOKEN)
         {
             // clock the actual data transfer and receive the bytes; spi_read automatically finds the Data Block
             for (i = 0; i < 512; i++)
                mmc_buffer = spiSendByte(0xff);         // is executed with card inserted

             // get CRC bytes (not really needed by us, but required by MMC)
             spiSendByte(0xff);
             spiSendByte(0xff);
             rvalue = MMC_SUCCESS;
         }
         else
         {
             // the data token was never received
             rvalue = MMC_DATA_TOKEN_ERROR;                   // 3
         }
      }
      else
      {
         // the MMC never acknowledge the read command
         rvalue = MMC_RESPONSE_ERROR;                          // 2
      }
   }
   else
   {
      rvalue = MMC_BLOCK_SET_ERROR;                           // 1
   }
   CS_HIGH ();
   spiSendByte(0xff);
   return rvalue;
}                                                                                 // mmc_read_block


//---------------------------------------------------------------------
// Ti Modification: long int -> long
char mmcWriteBlock (const unsigned long address)
{
   unsigned long i = 0;
   char rvalue = MMC_RESPONSE_ERROR;                        // MMC_SUCCESS;
   char c = 0x00;

   // Set the block length to read
   if (mmcSetBlockLength (512) == MMC_SUCCESS)       // block length could be set
   {
      // SS = LOW (on)
      CS_LOW ();
      // send write command
      mmcSendCmd (24,address, 0xFF);

      // check if the MMC acknowledged the write block command
      // it will do this by sending an affirmative response
      // in the R1 format (0x00 is no errors)
      if (mmcGetXXResponse(MMC_R1_RESPONSE) == MMC_R1_RESPONSE)
      {
         spiSendByte(0xff);
         // send the data token to signify the start of the data
         spiSendByte(0xfe);
         // clock the actual data transfer and transmitt the bytes
         for (i = 0; i < 512; i++)
             spiSendByte(mmc_buffer);                        // mmc_buffer;           Test: i & 0xff
         // put CRC bytes (not really needed by us, but required by MMC)
         spiSendByte(0xff);
         spiSendByte(0xff);
         // read the data response xxx0<status>1 : status 010: Data accected, status 101: Data
         //    rejected due to a crc error, status 110: Data rejected due to a Write error.
         mmcCheckBusy();
      }
      else
      {
         // the MMC never acknowledge the write command
         rvalue = MMC_RESPONSE_ERROR;                          // 2
      }
   }
   else
   {
      rvalue = MMC_BLOCK_SET_ERROR;                           // 1
   }
   // give the MMC the required clocks to finish up what ever it needs to do
   //   for (i = 0; i < 9; ++i)
   //      spiSendByte(0xff);

   CS_HIGH ();
   // Send 8 Clock pulses of delay.
   spiSendByte(0xff);
   return rvalue;
}                                                                                 // mmc_write_block


//---------------------------------------------------------------------
void mmcSendCmd (const char cmd, unsigned long data, const char crc)
{
   char frame[6];
   char temp;
   int i;

   frame[0]=(cmd|0x40);
   for(i=3;i>=0;i--)
   {
      temp=(char)(data>>(8*i));
      frame[4-i]=(temp);
   }
   frame[5]=(crc);
   for(i=0;i<6;i++)
      spiSendByte(frame);
}


//--------------- set blocklength 2^n ------------------------------------------------------
// Ti Modification: long int-> long
char mmcSetBlockLength (const unsigned long blocklength)
{
   char rValue = MMC_TIMEOUT_ERROR;
   char i = 0;

   // SS = LOW (on)
   CS_LOW ();

   // Set the block length to read
   //MMC_SET_BLOCKLEN =CMD16
   mmcSendCmd(16, blocklength, 0xFF);

   // get response from MMC - make sure that its 0x00 (R1 ok response format)
   if(mmcGetResponse()!=0x00);

   CS_HIGH ();

   // Send 8 Clock pulses of delay.
   spiSendByte(0xff);

   return MMC_SUCCESS;
}                                                                                 // block_length


//TI added substitution routine for spi_read and spi_write

unsigned char spiSendByte(const unsigned char data)
{
   while ((IFG2&UTXIFG1) ==0);                                  // wait while not ready / for RX
   TXBUF1 = data;                                                        // write
   while ((IFG2 & URXIFG1)==0);                                // wait for RX buffer (full)
   return (RXBUF1);
}


// Reading the contents of the CSD and CID registers in SPI mode is a simple
// read-block transaction.

char mmcReadRegister (const char cmd_register, const unsigned char length)
{
   char uc = 0;
   char rvalue = MMC_TIMEOUT_ERROR;
   //   char i = 0;

   if (mmcSetBlockLength (length) == MMC_SUCCESS)
   {
      CS_LOW ();
      // CRC not used: 0xff as last byte
      mmcSendCmd(cmd_register, 0x000000, 0xff);

      // wait for response
      // in the R1 format (0x00 is no errors)
      if (mmcGetResponse() == 0x00)
      {
         if (mmcGetXXResponse(0xfe)== 0xfe)
             for (uc = 0; uc < length; uc++)
                mmc_buffer[uc] = spiSendByte(0xff);
         // get CRC bytes (not really needed by us, but required by MMC)
         spiSendByte(0xff);
         spiSendByte(0xff);
      }
      else
         rvalue = MMC_RESPONSE_ERROR;
      // CS = HIGH (off)
      CS_HIGH ();

      // Send 8 Clock pulses of delay.
      spiSendByte(0xff);
   }
   CS_HIGH ();
   return rvalue;
}                                                                                 // mmc_read_register


//---------------------------------------------------------------------
#endif                                                                        /* _MMCLIB_C */

led.h
/*
  * ----------------------------------------------------------------------------
  * "THE BEER-WARE LICENSE" (Revision 43):
  * Rolf Freitag (webmaster at true-random.com) wrote this file.
  * As long as you retain this notice you can do whatever
  * the LGPL (Lesser GNU public License) allows with this stuff.
  * If you think this stuff is worth it, you can send me money via
  * paypal or if we met some day you can buy me a beer in return.
  * ----------------------------------------------------------------------------
  */
#ifndef _LED_H
#define _LED_H
#include   <msp430x14x.h>

#define GREEN_LED_ON()   P4OUT |=   0x02
#define GREEN_LED_OFF() P4OUT &= ~0x02

#define RED_LED_ON()      P4OUT |=   0x01
#define RED_LED_OFF()    P4OUT &= ~0x01

void initLED(void);
#endif

led.c
/*
  * ----------------------------------------------------------------------------
  * "THE BEER-WARE LICENSE" (Revision 44):
  * Rolf Freitag (webmaster at true-random.com) wrote this file.
  * As long as you retain this notice you can do whatever
  * the LGPL (Lesser GNU public License) allows with this stuff.
  * If you think this stuff is worth it, you can send me money via
  * paypal or if we met some day you can buy me a beer in return.
  * ----------------------------------------------------------------------------
  */
#include   <msp430x14x.h>

void initLED(void)
{
   P4DIR |= 0x03;
   P4SEL &= ~0x03;
   P4OUT = 0x03;
}
我要评论
  • 匿名发表
  • [添加到收藏夹]
  • 发表评论:(匿名发表无需登录,已登录用户可直接发表。) 登录状态:未登录
最新评论
所有评论[0]
    暂无已审核评论!

网站导航 管理登陆 ┊ 免责声明 问题反馈  友链说明
本站部分内容来自网络共享资源,如有冒犯您的权利请来信告之删除或纠正!
不得对本站进行复制、盗链或镜像,转载内容须获得同意或授权;欢迎友情链接、站务合作!

    我要报警 Alexa
 mcusy_cn#126.com (请把#改成@) 交流:522422171
本站学习交流群:138..158(高级群1-)、77930286(高级群2)、61804809(群3)
Copyright© MCUSY All Rights Reserved
本站网警备案号: WZ36040002485
  ICP备案证书号:粤ICP备09034963号