[C7] Tổng kết và bài tập về giao thức SPI

tranhai20511

Thành Viên PIF
Chào các em. :1cool_byebye:

Sau khi được học về giao tiếp SPI trong lớp, và giao tiếp được với IC 74HC595 các em sẽ làm một bài tập để củng cố kiến thức.

Trước tiên. Đây là 2 file driver anh đã viết cho giao thức SPI : SPI.c SPI.h

Trong 2 file trên gồm các lệnh cấu hình cho 2 module SPI USCIA0, module SPI USCIB0 và IC EEPROM 93LC46B.

Và slide bài giảng SPI:
<<Tổng hợp Bài giảng và Drivers C7 >>

Bài tập:

Các em hãy viết code để giao tiếp với IC Serial Flash EN25T80 bằng module SPI của MSP430G2553.

Sau đó các em hãy thử hiển thị led 7 đoạn bằng cách :
1/ Các em truyền một chuỗi data giải mã hiển thị led 7 đoạn từ số 0 đến số 9 xuống vùng địa chỉ cố định trên IC EN25T80
2/ Các em truyền lệnh từ MSP430 xuống IC EN25T80 để gửi data đã truyền ở trên qua IC 74HC595 để hiển thị lên led 7 đoạn.

Đây schematic để các em tham khảo:
Capture.JPG


Một số chú ý:
1/** Các em phải đọc kỹ datasheet của IC EN25T80: link
2/ Các em chú ý bảng mã lệnh để gửi lệnh cho đúng
3/ Các em chú ý để bắt đầu nghi dữ liệu đầu tiên phải gửi lệnh để bật Write Enable ( code: 06h )
và sau khi nghi xong phải tắt nó ( code: 04h)
4/ Khi dữ liệu nghi nhiều lần, để nghi dữ liệu mới vào thanh nghi cũ phải dùng lệnh để xóa data cũ
(code: C7h // xóa toàn bộ hoàn thành trong 20s )

Chúc các em thành công.
 

thanh_dien1992

Trứng gà
Chào anh tranhai20511 , em đang làm đề tài về đọc ghi eeprom EN25T80 dùng msp430g2553 nên rất cần thư viện spi.c và spi.h ở trên nhưng link die rùi không xem được, nhờ anh gửi lại cho em dùm! thanks anh nhiều!
 

thanh_dien1992

Trứng gà
em nhận được rồi! thanks a nhiều nhe! em đang thử tìm hiều giao tiếp SPI nên e cũng thử dùng cách set/clear bit để truyền nhận.
em tạo 1 thư viện spi.h và 1 thư viện EEPROM_EN25T80.h để thực hiện giao tiếp giữa msp430g2553 với EN25T80 như sau:

//2death: Em nên dùng tab [ CODE ] cho gọn phần code/
Code:
//-----------------------------------spi.h----------------------------------------------------------------------------------
 
#include "msp430g2553.h"
#defineINIT_PORT()init_port()/* Initialize MMC control port (CS/CLK/DI:output, DO:input) */
 
#define CS_PORT P2OUT //CS port
#define CK_PORT P2OUT //CK port
#define DI_PORT P2OUT //DI port
#define DO_PORT P2IN //DO port
#define CS BIT0 //CS pin
#define CK BIT1 //CK pin
#define DI BIT2 //DI pin
#define DO_ BIT3 //DO pin
#define CS_H() CS_PORT |= CS //CS pin
#define CS_L()CS_PORT &= ~CS//CS pin
#define CK_H()CK_PORT |= CK //CK pinini bir yap.
#defineCK_L()CK_PORT &= ~CK//CK pinini sýfýr yap.
#define DI_H()DI_PORT |= DI //DI pinini bir yap.
#define DI_L()DI_PORT &= ~DI//DI pinini sýfýr yap.
#define DO DO_PORT & DO_ //DO pinindeki veriyi oku.
 
 
 
void init_port(void){
P2DIR = 0x07;
P2REN = 0X0F;
}
 
/*-----------------------------------------------------------------------*/
/* Transmit a byte to eeprom */
/*-----------------------------------------------------------------------*/
 
static
void tbyte (unsigned char d)/* Data to be sent */
{
if (d & 0x20) DI_H(); else DI_L();/* bit7 */
CK_H(); CK_L();
if (d & 0x0) DI_H(); else DI_L();/* bit6 */
CK_H(); CK_L();
if (d & 0x20) DI_H(); else DI_L();/* bit5 */
CK_H(); CK_L();
if (d & 0x10) DI_H(); else DI_L();/* bit */
CK_H(); CK_L();
if (d & 0x02) DI_H(); else DI_L();/* bit3 */
CK_H(); CK_L();
if (d & 0x0) DI_H(); else DI_L();/* bit2 */
CK_H(); CK_L();
if (d & 0x02) DI_H(); else DI_L();/* bit1 */
CK_H(); CK_L();
if (d & 0x01) DI_H(); else DI_L();/* bit0 */
CK_H(); CK_L();
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Receive a byte from eeprom */
/*-----------------------------------------------------------------------*/
 
static
unsigned char rbyte (void)
{
unsigned char r;
 
DI_H();/* Send 0xFF */
 
CK_L();
r = 0; if (DO) r++;/* bit7 */
CK_H(); CK_L();
r <<= 1; if (DO) r++;/* bit6 */
CK_H(); CK_L();
r <<= 1; if (DO) r++;/* bit5 */
CK_H(); CK_L();
r <<= 1; if (DO) r++;/* bit */
CK_H(); CK_L();
r <<= 1; if (DO) r++;/* bit3 */
CK_H(); CK_L();
r <<= 1; if (DO) r++;/* bit2 */
CK_H(); CK_L();
r <<= 1; if (DO) r++;/* bit1 */
CK_H(); CK_L();
r <<= 1; if (DO) r++;/* bit0 */
CK_H(); CK_L();
 
return r;
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Skip bytes on the MMC (bitbanging) */
/*-----------------------------------------------------------------------*/
 
static
void skip_xbyte (unsigned short n)/* Number of bytes to skip */
{
DI_H();/* Send 0xFF */
 
do {
CK_H(); CK_L();
CK_H(); CK_L();
CK_H();CK_L();
CK_H(); CK_L();
CK_H(); CK_L();
CK_H(); CK_L();
CK_H(); CK_L();
CK_H(); CK_L();
} while (--n);
}
 
 
 
/*-----------------------------------------------------------------------*/
/* Deselect the card and release SPI bus */
/*-----------------------------------------------------------------------*/
 
static
void release_spi (void)
{
CS_H();
rbyte();
}
 
//-----------------------------------EEPROM_EN25T80.h--------------------------------------------------------------------------------------------------------
 
#include "spi.h"
 
//WRITE ENABLE
void write_enable(void)
{
CS_L();
__delay_cycles(20);
tbyte(0x06);
CS_H();
}
 
//WRITE DISABLE
void write_disable(void)
{
CS_L();
__delay_cycles(20);
tbyte(0x04);
CS_H();
}
//READ STATUS REGISTER
unsigned char Read_status_res(void)
{
unsigned char r;
CS_L();
__delay_cycles(20);
tbyte(0x05);
r = rbyte();
CS_H();
 
return r;
}
 
//WRITE STATUS REGISTER
void Write_status_res(unsigned char d)
{
CS_L();
__delay_cycles(20);
tbyte(0x01);
tbyte(d);
CS_H();
 
}
// READ 1 BYTE
unsigned char read_1byte( unsigned long y )// doc 1 byte bat dau tu bit co address y
{ unsigned char add1,add2,add3;
unsigned char data;
add1 = (y>>16)&0xff;
add2 = (y>>8)&0xff;
add3 = y&0xff;
 
CS_L();
__delay_cycles(20);
tbyte(0x03);
tbyte(add1);
tbyte(add2);
tbyte(add3);
 
data = rbyte();
CS_H();
return data;
}
 
// READ x BYTE
void read_xbyte( unsigned char *buff, int x, unsigned long y )// doc x byte (max:512)bat dau tu bit co address y
{ unsigned char add1,add2,add3;
 
add1 = (y>>16)&0xff;
add2 = (y>>8)&0xff;
add3 = y&0xff;
 
CS_L();
__delay_cycles(20);
tbyte(0x03);
tbyte(add1);
tbyte(add2);
tbyte(add3);
 
for(int i=0;i<x;i++)
{
*buff++ = rbyte();
}
CS_H();
 
 
}
//PAGE PROGRAM- WRITE DATA
void write_xdata(unsigned char *buff, int x,unsigned long y)//ghi x byte vao trong eeprom tu vi tri address bit la y
{
unsigned char add1,add2,add3;
add1 = (y>>16)&0xff;
add2 = (y>>8)&0xff;
add3 = y&0xff;
 
write_enable();
CS_L();
__delay_cycles(20);
tbyte(0x02);
tbyte(add1);
tbyte(add2);
tbyte(add3);
 
for(int i=0;i<x;i++)
{
tbyte(buff[I]);[/I]
[I] }[/I]
[I] CS_H();[/I]
[I] write_disable();[/I]
[I]}[/I]
 
[I]// XOA SECTOR[/I]
[I]void Sector_Eraser ( unsigned long y )// doc 1 byte bat dau tu bit co address y[/I]
[I]{ unsigned char add1,add2,add3;[/I]
[I] add1 = (y>>16)&0xff;[/I]
[I] add2 = (y>>8)&0xff;[/I]
[I] add3 = y&0xff;[/I]
 
[I] CS_L();[/I]
[I] __delay_cycles(20);[/I]
[I] tbyte(0x20);[/I]
[I] tbyte(add1);[/I]
[I] tbyte(add2);[/I]
[I] tbyte(add3);[/I]
 
[I] CS_H();[/I]
[I] }[/I]
[I]//-----------------------------------main.c----------------------------------------------------------------------------------------------------------[/I]
 
[I]#include "msp430g2553.h"[/I]
[I]#include "epprom_EN25T80.h"[/I]
 
[I]unsigned char buff[350];[/I]
[I]unsigned char xbuff[28]={1,2,3,4,14,1,0, 1,2,3,4,14,2,0, 1,5,3,4,14,1,0, 1,2,3,4,14,1,0xff}; [/I]
 
[I]void main( void )[/I]
[I]{[/I]
[I] // Stop watchdog timer to prevent time out reset[/I]
[I] WDTCTL = WDTPW + WDTHOLD;[/I]
[I] BCSCTL1 = CALBC1_8MHZ; // Set DCO[/I]
[I] DCOCTL = CALDCO_8MHZ;[/I]
 
 
[I] P1DIR |= BIT0;[/I]
[I] P1OUT &= ~BIT4;[/I]
[I] P1OUT &= ~BIT0;[/I]
 
[I] //read_xbyte(buff,28,0);[/I]
[I]__delay_cycles(200000);[/I]
 
[I] Sector_Eraser(0); //xoa sector 0[/I]
[I]__delay_cycles(200000);[/I]
 
[I] write_xdata(xbuff, 28,0); //ghi mang xbuff co 28 byte vao dia chi 000000h[/I]
[I] __delay_cycles(2000000);[/I]
 
[I] read_xbyte(buff,28,0); //doc 28 byte tu eeprom có dia chi bat dau tu 000000h va luu vao mang buff[/I]
[I]__delay_cycles(200000);[/I]
 
 
[I]//gui buff len may tinh qua uart khi nhan duoc byte 0x31 tu may tinh gui xuong[/I]
[I]P1SEL |= BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD[/I]
[I]P1SEL2 |= BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD[/I]
 
[I]UCA0CTL1 |= UCSSEL_2; // SMCLK[/I]
[I]UCA0BR0 = 0X41; //8Mhz-9600, //104: 1MHz 9600[/I]
[I]UCA0BR1 = 3; //8Mhz-9600, //0: 1MHz 9600[/I]
[I]UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1[/I]
[I]UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**[/I]
[I]IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt[/I]
 
[I]__bis_SR_register(LPM0_bits +GIE); // Enter LPM0, interrupts enabled[/I]
[I]}[/I]
 
[I]// Echo back RXed character, confirm TX buffer is ready first[/I]
[I]#pragma vector=USCIAB0RX_VECTOR[/I]
[I]__interrupt void USCI0RX_ISR(void)[/I]
[I]{[/I]
 
[I] if(UCA0RXBUF==0x31) //neu nhan duoc 0x31 tu may tinh gui xuong thi se truyen mang buff len may tinh[/I]
[I] {[/I]
[I] P1OUT |= BIT0; //toggle led P1.0[/I]
[I]__delay_cycles(200000);[/I]
[I]P1OUT &= ~BIT0;[/I]
[I]__delay_cycles(200000);[/I]
 
[I] for(int i=0;i<28;i++)[/I]
[I] {[/I]
[I] while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?[/I]
[I] UCA0TXBUF = buff[I]; // TX -> RXed character[/I][/I]
[I] }[/I]
[I] }[/I]
[I]}[/I]
Code trên có ở link: http://www.mediafire.com/download/kilq808qqao303f/code epprom.rar

Em đã test truyền uart rồi nên truyền uart không bị lỗi, vấn đề là chưa ghi vào được epprom nên dữ liệu truyền lên máy tính bị sai đi, nó cứ là 0xff , nhưng em không hiểu còn chỗ nào chưa đúng nữa, em cũng thử cách cho thêm thời gian delay giữa các xung clock của chân CK nhưng vẫn chưa được. Nhờ anh và mọi người xem giúp dùm em bị lỗi gì mà sao cứ bị truyền nhận sai mãi!
chân thành cảm ơn anh và mọi người!
 

thanh_dien1992

Trứng gà
mình đã giao tiếp và ghi đọc được cho EN25T80 rồi nhưng sao chỉ ghi được vào 256 byte thấp của mỗi sector thôi, không biết còn thiếu config gì không mà nó chẳng ghi được 256 byte cao nữa! ai có kinh nghiệm với con này rồi cho mình xin ý kiến với!
 
Top