找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2562|回复: 1
打印 上一主题 下一主题
收起左侧

C8051F020的spi源代码 SPI0_Master,Slave,SPI0_EEPROM_Polled_Mode

[复制链接]
跳转到指定楼层
楼主


SPI0_EEPROM_Polled_Mode单片机源程序如下:
  1. //-----------------------------------------------------------------------------
  2. // F02x_SPI0_EEPROM_Polled_Mode.c
  3. //-----------------------------------------------------------------------------
  4. // 此程序由【达达电子工作】的 RJ 整理 我们对此无版权
  5. // 关于此例程请参考         C8051F2xx中文版.pdf 的第 19 章:串行外设接口总线(SPI0)
  6. //
  7. // Copyright 2006 Silicon Laboratories, Inc.
  8. //
  9. // Program Description:
  10. //
  11. // This program accesses a SPI EEPROM using polled mode access. The 'F02x MCU
  12. // is configured in 4-wire Single Master Mode, and the EEPROM is the only
  13. // slave device connected to the SPI bus. The read/write operations are
  14. // tailored to access a Microchip 4 kB EEPROM 25LC320. The relevant hardware
  15. // connections of the 'F02x MCU are shown here:
  16. //
  17. // P0.0 - UART TXD   (digital output, push-pull)
  18. // P0.1 - UART RXD   (digital input, open-drain)
  19. // P0.2 - SPI SCK    (digital output, push-pull)
  20. // P0.3 - SPI MISO   (digital input, open-drain)
  21. // P0.4 - SPI MOSI   (digital output, push-pull)
  22. // P0.5 - SPI NSS    (digital input, open-drain) (unused in single master mode)
  23. // P0.6 - GPIO (NSS) (digital output, push-pull) (used as slave select output)
  24. // P1.6 - LED        (digital output, push-pull)
  25. //
  26. // External crystal - 22.1184 MHz
  27. //
  28. // How To Test:
  29. //
  30. // Method1:
  31. // 1) Download the code to a 'F02x device that is connected as above.
  32. // 2) Run the code. The LED will blink fast during the write/read/verify
  33. //    operations.
  34. // 3) If the verification passes, the LED will blink slowly. If it fails,
  35. //    the LED will be OFF.
  36. //
  37. // Method2 (optional):
  38. // 1) Download code to a 'F02x device that is connected as above, and
  39. //    also connected to a RS232 transceiver.
  40. // 2) Connect a straight serial cable from the RS232 transceiver to a PC.
  41. // 3) On the PC, open HyperTerminal (or any other terminal program) and connect
  42. //    to the COM port at <BAUDRATE> and 8-N-1.
  43. // 4) HyperTerminal will print the progress of the write/read operation, and in
  44. //    the end will print the test result as pass or fail. Additionally, if the
  45. //    verification passes, the LED will blink slowly. If it fails, the LED will
  46. //    be OFF.
  47. //
  48. //
  49. // Target:         C8051F02x
  50. // Tool chain:     Keil C51 7.50 / Keil EVAL C51
  51. // Command Line:   None
  52. //
  53. // Release 1.0
  54. //    -Initial Revision (PKC)
  55. //    -31 MAY 2006
  56. //

  57. //-----------------------------------------------------------------------------
  58. // Includes
  59. //-----------------------------------------------------------------------------
  60. #include <C8051F020.h>                 // SFR declarations
  61. #include <stdio.h>                     // printf is declared here

  62. //-----------------------------------------------------------------------------
  63. // 16-bit SFR Definitions for the 'F02x
  64. //-----------------------------------------------------------------------------
  65. sfr16 TMR2     = 0xCC;                 // Timer2 low and high bytes together

  66. //-----------------------------------------------------------------------------
  67. // User-defined types, structures, unions etc
  68. //-----------------------------------------------------------------------------
  69. #ifndef BYTE
  70. #define BYTE unsigned char
  71. #endif

  72. #ifndef UINT
  73. #define UINT unsigned int
  74. #endif

  75. //-----------------------------------------------------------------------------
  76. // Global Constants
  77. //-----------------------------------------------------------------------------
  78. #define SYSCLK             22118400    // External crystal frequency in Hz
  79. #define BAUDRATE           115200      // Baud rate of UART in bps

  80. // Microchip 25AA320 Slave EEPROM Parameters
  81. #define  F_SCK_MAX         2000000     // Max SCK freq (Hz)
  82. #define  T_NSS_DISABLE_MIN 500         // Min NSS disable time (ns)
  83. #define  EEPROM_CAPACITY   4096        // EEPROM capacity (bytes)

  84. // EEPROM Instruction Set
  85. #define  EEPROM_CMD_READ   0x03        // Read Command
  86. #define  EEPROM_CMD_WRITE  0x02        // Write Command
  87. #define  EEPROM_CMD_WRDI   0x04        // Reset Write Enable Latch Command
  88. #define  EEPROM_CMD_WREN   0x06        // Set Write Enable Latch Command
  89. #define  EEPROM_CMD_RDSR   0x05        // Read Status Register Command
  90. #define  EEPROM_CMD_WRSR   0x01        // Write Status Register Command

  91. sbit LED = P1^6;                       // LED='1' means ON
  92. sbit EEPROM_CS = P0^6;                 // Active low chip select for EEPROM

  93. //-----------------------------------------------------------------------------
  94. // Function Prototypes
  95. //-----------------------------------------------------------------------------
  96. void Reset_Sources_Init (void);
  97. void OSCILLATOR_Init (void);
  98. void PORT_Init (void);
  99. void TIMER2_Init (void);
  100. void UART0_Init (void);
  101. void SPI0_Init (void);
  102. void Init_Device (void);

  103. void Delay_us (BYTE time_us);
  104. void Delay_ms (BYTE time_ms);
  105. void EEPROM_Write (UINT address, BYTE value);
  106. BYTE EEPROM_Read (UINT address);

  107. //-----------------------------------------------------------------------------
  108. // main() Routine
  109. //-----------------------------------------------------------------------------
  110. void main (void)
  111. {
  112.    UINT  address;                      // EEPROM address
  113.    BYTE  test_byte;                    // Used as a temporary variable
  114.    
  115.    Init_Device ();                     // Initializes hardware peripherals
  116.    
  117.    // The following code will test the EEPROM by performing write/read/verify
  118.    // operations. The first test will write 0xFFs to the EEPROM, and the
  119.    // second test will write the LSBs of the EEPROM addresses.

  120.    // Fill EEPROM with 0xFF's
  121.    LED = 1;
  122.    printf("Filling with 0xFF's...\n");
  123.    for (address = 0; address < EEPROM_CAPACITY; address++)
  124.    {
  125.       test_byte = 0xFF;
  126.       EEPROM_Write (address, test_byte);

  127.       // Print status to UART0
  128.       if ((address % 16) == 0)
  129.       {
  130.          printf ("\nWriting 0x%04x: %02x ", address, (UINT)test_byte);
  131.          LED = ~LED;
  132.       }
  133.       else
  134.          printf ("%02x ", (UINT)test_byte);
  135.    }

  136.    // Verify EEPROM with 0xFF's
  137.    printf("\n\nVerifying 0xFF's...\n");
  138.    for (address = 0; address < EEPROM_CAPACITY; address++)
  139.    {
  140.       test_byte = EEPROM_Read (address);

  141.       // Print status to UART0
  142.       if ((address % 16) == 0)
  143.       {
  144.          printf ("\nVerifying 0x%04x: %02x ", address, (UINT)test_byte);
  145.          LED = ~LED;
  146.       }
  147.       else
  148.          printf ("%02x ", (UINT)test_byte);
  149.       if (test_byte != 0xFF)
  150.       {
  151.          LED = 0;
  152.          printf ("Error at %u\n", address);
  153.          while (1);                    // Stop here on error (for debugging)
  154.       }
  155.    }

  156.    // Fill EEPROM with LSB of EEPROM addresses
  157.    printf("\n\nFilling with LSB of EEPROM addresses...\n");
  158.    for (address = 0; address < EEPROM_CAPACITY; address++)
  159.    {
  160.       test_byte = address & 0xFF;
  161.       EEPROM_Write (address, test_byte);

  162.       // Print status to UART0
  163.       if ((address % 16) == 0)
  164.       {
  165.          printf ("\nWriting 0x%04x: %02x ", address, (UINT)test_byte);
  166.          LED = ~LED;
  167.       }
  168.       else
  169.          printf ("%02x ", (UINT)test_byte);
  170.    }

  171.    // Verify EEPROM with LSB of EEPROM addresses
  172.    printf("\n\nVerifying LSB of EEPROM addresses...\n");
  173.    for (address = 0; address < EEPROM_CAPACITY; address++)
  174.    {
  175.       test_byte = EEPROM_Read (address);

  176.       // print status to UART0
  177.       if ((address % 16) == 0)
  178.       {
  179.          printf ("\nVerifying 0x%04x: %02x ", address, (UINT)test_byte);
  180.          LED = ~LED;
  181.       }
  182.       else
  183.          printf ("%02x ", (UINT)test_byte);
  184.       
  185.       if (test_byte != (address & 0xFF))
  186.       {
  187.          LED = 0;
  188.          printf ("Error at %u\n", address);
  189.          while (1);                    // Stop here on error (for debugging)
  190.       }
  191.    }

  192.    printf ("\n\nVerification success!\n");
  193.    
  194.    while (1)                           // Loop forever
  195.    {                                   
  196.       LED = ~LED;                      // Flash LED when done (all verified)
  197.       Delay_ms (200);
  198.    }
  199. }

  200. //-----------------------------------------------------------------------------
  201. // Initialization Subroutines
  202. //-----------------------------------------------------------------------------

  203. //-----------------------------------------------------------------------------
  204. // PCA0_Init
  205. //-----------------------------------------------------------------------------
  206. //
  207. // Return Value : None
  208. // Parameters   : None
  209. //
  210. // This function disables the watchdog timer.
  211. //
  212. //-----------------------------------------------------------------------------
  213. void Reset_Sources_Init (void)
  214. {
  215.    WDTCN = 0xDE;                       // Disable WDT
  216.    WDTCN = 0xAD;
  217. }

  218. //-----------------------------------------------------------------------------
  219. // OSCILLATOR_Init
  220. //-----------------------------------------------------------------------------
  221. //
  222. // Return Value : None
  223. // Parameters   : None
  224. //
  225. // This function initializes the system clock to use the external crystal
  226. // at 22.1184 MHz.
  227. //
  228. //-----------------------------------------------------------------------------
  229. void OSCILLATOR_Init (void)
  230. {
  231.    int i = 0;
  232.    OSCXCN    = 0x67;
  233.    for (i = 0; i < 3000; i++);         // Wait 1ms for initialization
  234.    while ((OSCXCN & 0x80) == 0);
  235.    OSCICN    = 0x0B;
  236. }

  237. //-----------------------------------------------------------------------------
  238. // PORT_Init
  239. //-----------------------------------------------------------------------------
  240. //
  241. // Return Value : None
  242. // Parameters   : None
  243. //
  244. // This function configures the crossbar and GPIO ports.
  245. //
  246. // P0.0  -  TX0 (UART0), Push-Pull,  Digital
  247. // P0.1  -  RX0 (UART0), Open-Drain, Digital
  248. // P0.2  -  SCK  (SPI0), Push-Pull,  Digital
  249. // P0.3  -  MISO (SPI0), Open-Drain, Digital
  250. // P0.4  -  MOSI (SPI0), Push-Pull,  Digital
  251. // P0.5  -  NSS  (SPI0), Open-Drain, Digital (Not used in single master mode)
  252. // P0.6  -  Unassigned,  Push-Pull,  Digital (Used as NSS slave select output)
  253. // P0.7  -  Unassigned,  Open-Drain, Digital

  254. // P1.0  -  Unassigned,  Open-Drain, Digital
  255. // P1.1  -  Unassigned,  Open-Drain, Digital
  256. // P1.2  -  Unassigned,  Open-Drain, Digital
  257. // P1.3  -  Unassigned,  Open-Drain, Digital
  258. // P1.4  -  Unassigned,  Open-Drain, Digital
  259. // P1.5  -  Unassigned,  Open-Drain, Digital
  260. // P1.6  -  Unassigned,  Push-Pull,  Digital (LED D3 - Target Board)
  261. // P1.7  -  Unassigned,  Open-Drain, Digital

  262. // P2.0  -  Unassigned,  Open-Drain, Digital
  263. // P2.1  -  Unassigned,  Open-Drain, Digital
  264. // P2.2  -  Unassigned,  Open-Drain, Digital
  265. // P2.3  -  Unassigned,  Open-Drain, Digital
  266. // P2.4  -  Unassigned,  Open-Drain, Digital
  267. // P2.5  -  Unassigned,  Open-Drain, Digital
  268. // P2.6  -  Unassigned,  Open-Drain, Digital
  269. // P2.7  -  Unassigned,  Open-Drain, Digital

  270. // P3.0  -  Unassigned,  Open-Drain, Digital
  271. // P3.1  -  Unassigned,  Open-Drain, Digital
  272. // P3.2  -  Unassigned,  Open-Drain, Digital
  273. // P3.3  -  Unassigned,  Open-Drain, Digital
  274. // P3.4  -  Unassigned,  Open-Drain, Digital
  275. // P3.5  -  Unassigned,  Open-Drain, Digital
  276. // P3.6  -  Unassigned,  Open-Drain, Digital
  277. // P3.7  -  Unassigned,  Open-Drain, Digital (Switch SW2 - Target Board)
  278. //
  279. //-----------------------------------------------------------------------------
  280. void PORT_Init (void)
  281. {
  282.    P0MDOUT   = 0x55;
  283.    P1MDOUT   = 0x40;
  284.    XBR0      = 0x06;
  285.    XBR2      = 0x40;
  286. }  

  287. //-----------------------------------------------------------------------------
  288. // TIMER2_Init
  289. //-----------------------------------------------------------------------------
  290. //
  291. // Return Value : None
  292. // Parameters   : None
  293. //
  294. // Initializes Timer2 to be clocked by SYSCLK for use as a delay timer.
  295. //
  296. //-----------------------------------------------------------------------------
  297. void TIMER2_Init (void)
  298. {
  299.    CKCON    |= 0x20;
  300. }

  301. //-----------------------------------------------------------------------------
  302. // UART0_Init
  303. //-----------------------------------------------------------------------------
  304. //
  305. // Return Value : None
  306. // Parameters   : None
  307. //
  308. // Configures the UART0 using Timer1, for <BAUDRATE> and 8-N-1. Once this is
  309. // set up, the standard printf function can be used to output data.
  310. //
  311. //-----------------------------------------------------------------------------
  312. void UART0_Init (void)
  313. {
  314.    TMOD   = 0x20;                      // TMOD: timer 1, mode 2, 8-bit reload
  315.    TH1    = -(SYSCLK/BAUDRATE/16);     // set Timer1 reload value for baudrate
  316.    TL1    = TH1;                       // set Timer1 initial value
  317.    CKCON |= 0x10;                      // Timer1 uses SYSCLK as time base
  318.    PCON  |= 0x80;                      // SMOD0 = 1
  319.    TR1    = 1;                         // start Timer1

  320.    SCON0  = 0x50;                      // UART mode 1, 8-bit UART, enable RX
  321.    TI0   = 1;                          // Indicate TX0 ready
  322. }

  323. //-----------------------------------------------------------------------------
  324. // SPI0_Init
  325. //-----------------------------------------------------------------------------
  326. //
  327. // Return Value : None
  328. // Parameters   : None
  329. //
  330. // Configures SPI0 to use 4-wire Single-Master mode. The SPI timing is
  331. // configured for Mode 0,0 (data centered on first edge of clock phase and
  332. // SCK line low in idle state). The SPI clock is set to 1.6 MHz (nominal).
  333. // The slave select pin is set to 1.
  334. //
  335. //-----------------------------------------------------------------------------
  336. void SPI0_Init()
  337. {
  338.    SPI0CFG     = 0x07;                 // Data sampled on 1st SCK rising edge
  339.                                        // 8-bit data words

  340.    SPI0CN      = 0x03;                 // Master mode; SPI enabled; flags
  341.                                        // cleared

  342.    // Note: This example uses the external crystal as SYSCLK.
  343.    // The equation for SPI0CKR is (SYSCLK/(2*F_SCK_MAX))-1, but this yields
  344.    // a SPI frequency that is slightly more than 2 MHz. But, 2 MHz is the max
  345.    // frequency spec of the EEPROM used here. So, the "-1" term is omitted
  346.    // in the following usage:   
  347.    SPI0CKR     = (SYSCLK/(2*F_SCK_MAX));
  348.    
  349.    EEPROM_CS   = 1;                    // Deactivate Slave Select
  350. }

  351. //-----------------------------------------------------------------------------
  352. // Init_Device
  353. //-----------------------------------------------------------------------------
  354. //
  355. // Return Value : None
  356. // Parameters   : None
  357. //
  358. // Calls all device initialization functions.
  359. //
  360. //-----------------------------------------------------------------------------
  361. void Init_Device (void)
  362. {
  363.    Reset_Sources_Init ();
  364.    OSCILLATOR_Init ();
  365.    PORT_Init ();
  366.    TIMER2_Init ();
  367.    UART0_Init ();
  368.    SPI0_Init ();
  369. }

  370. //-----------------------------------------------------------------------------
  371. // Support Subroutines
  372. //-----------------------------------------------------------------------------

  373. //-----------------------------------------------------------------------------
  374. // Delay_us
  375. //-----------------------------------------------------------------------------
  376. //
  377. // Return Value : None
  378. // Parameters   : 1. time_us - time delay in microseconds
  379. //                   range: 1 to 255
  380. //
  381. // Creates a delay for the specified time (in microseconds) using TIMER2. The
  382. // time tolerance is approximately +/-50 ns (1/SYSCLK + function call time).
  383. //
  384. //-----------------------------------------------------------------------------
  385. void Delay_us (BYTE time_us)
  386. {
  387.    TR2   = 0;                          // Stop timer
  388.    TF2   = 0;                          // Clear timer overflow flag
  389.    TMR2  = -( (UINT)(SYSCLK/1000000) * (UINT)(time_us) );
  390.    TR2   = 1;                          // Start timer
  391.    while (!TF2);                       // Wait till timer overflow occurs
  392.    TR2   = 0;                          // Stop timer
  393. }

  394. //-----------------------------------------------------------------------------
  395. // Delay_ms
  396. //-----------------------------------------------------------------------------
  397. //
  398. // Return Value : None
  399. // Parameters   : 1. time_ms - time delay in milliseconds
  400. //                   range: 1 to 255
  401. //
  402. // Creates a delay for the specified time (in milliseconds) using TIMER2. The
  403. // time tolerance is approximately +/-50 ns (1/SYSCLK + function call time).
  404. //
  405. //-----------------------------------------------------------------------------
  406. void Delay_ms (BYTE time_ms)
  407. {
  408.    BYTE i;

  409.    while(time_ms--)
  410.       for(i = 0; i< 10; i++)           // 10 * 100 microsecond delay
  411.          Delay_us (100);
  412. }

  413. //-----------------------------------------------------------------------------
  414. // EEPROM_Write
  415. //-----------------------------------------------------------------------------
  416. //
  417. // Return Value : None
  418. // Parameters   : 1. address - the destination EEPROM address.
  419. //                   range: 0 to EEPROM_CAPACITY
  420. //                2. value - the value to write.
  421. //                   range: 0x00 to 0xFF
  422. //
  423. // Writes one byte to the specified address in the EEPROM. This function polls
  424. // the EEPROM status register after the write operation, and returns only after
  425. // the status register indicates that the write cycle is complete. This is to
  426. // prevent from having to check the status register before a read operation.
  427. //
  428. //-----------------------------------------------------------------------------
  429. void EEPROM_Write (UINT address, BYTE value)
  430. {
  431.    // Writing a byte to the EEPROM is a five-step operation.
  432.    
  433.    // Step1: Set the Write Enable Latch to 1
  434.    EEPROM_CS   = 0;                    // Step1.1: Activate Slave Select
  435.    SPI0DAT  = EEPROM_CMD_WREN;         // Step1.2: Send the WREN command
  436.    while (!SPIF);                      // Step1.3: Wait for end of transfer
  437.    SPIF     = 0;                       // Step1.4: Clear the SPI intr. flag
  438.    EEPROM_CS   = 1;                    // Step1.5: Deactivate Slave Select
  439.    Delay_us (1);                       // Step1.6: Wait for at least
  440.                                        //          T_NSS_DISABLE_MIN
  441.    // Step2: Send the WRITE command
  442.    EEPROM_CS   = 0;
  443.    SPI0DAT  = EEPROM_CMD_WRITE;
  444.    while (!SPIF);
  445.    SPIF     = 0;
  446.    
  447.    // Step3: Send the EEPROM destination address (MSB first)
  448.    SPI0DAT  = (BYTE)((address >> 8) & 0x00FF);
  449.    while (!SPIF);
  450.    SPIF     = 0;
  451.    SPI0DAT  = (BYTE)(address & 0x00FF);
  452.    while (!SPIF);
  453.    SPIF     = 0;
  454.    
  455.    // Step4: Send the value to write
  456.    SPI0DAT  = value;
  457.    while (!SPIF);
  458.    SPIF     = 0;
  459.    EEPROM_CS   = 1;
  460.    Delay_us (1);
  461. ……………………

  462. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
SPI.zip (85.69 KB, 下载次数: 15)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:625070 发表于 2020-4-16 19:34 | 只看该作者
请问这个可以用来读SD卡吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表