我用的單片機(jī)是C8051,使用硬件SPI三線主方式與CH452連接
三線主方式指的是單片機(jī)的SPI方式,用一個(gè)GPIO連接CH452的LOAD
CH452的4線接口不是SPI接口
CH452的4線接口不是SPI接口?不是部分兼容嗎?我就硬要往SPI總線上掛!
不能往硬件SPI上面掛的。例子程序你可以下載CH372EV。ZIP,里面有451的4線制的例子程序
可以用SPI的,寫CH45X命令的步驟如下 1.原始輸入數(shù)據(jù)為12位,左移4位后變成16位(因?yàn)镾PI數(shù)據(jù)位總是8個(gè)倍數(shù)) 2.設(shè)置SPI為方式0(或方式3),CPOL=0,CPHA=0,低位在前LSB,產(chǎn)生LOAD片選低電平 3.SPI輸出一個(gè)字節(jié),先是16位的低字節(jié) 4.SPI輸出一個(gè)字節(jié),再是16位的高字節(jié) 5.結(jié)束LOAD片選 讀CH45X的命令,也就是讀鍵盤命令的步驟如下 1.設(shè)置SPI為方式0,CPOL=0,CPHA=0,高位在前MSB,產(chǎn)生LOAD片選低電平 2.SPI輸出一個(gè)字節(jié),數(shù)據(jù)是0EH或者0FEH 3.結(jié)束LOAD片選 4.SPI輸入一個(gè)字節(jié),該數(shù)據(jù)作為無符號(hào)數(shù)右移一位后就是鍵盤碼
這是一個(gè)硬件SPI和451相連接的例子程序,你可以參考,單片機(jī)是AVR的MEGA8: //ICC-AVR application builder : 2006-8-7 8:52:40 // Target : M8 // Crystal: 11.059Mhz #include #include #include #include #include #define CH452_SDA_SET PORTC|=(1<#define CH452_SDA_CLR PORTC&=~(1<#define CH452_SCL_SET PORTC|=(1<#define CH452_SCL_CLR PORTC&=~(1<#define DELAY_1US {mDelay1uS( );} #define CH452_SDA_IN ((PINC&0X10)!=0) #define CH452_WIRE ( PIND&0X04 ) void mDelay1uS( ) /* 至少延時(shí)1uS,根據(jù)單片機(jī)主頻調(diào)整 */ { unsigned char i; for ( i = 10; i != 0; i -- ); }
void Delay50ms( ) { unsigned char i, j; for ( i=200; i!=0; i-- ) for ( j=250; j!=0; j-- ); }
void init_CH452_IO() { PORTC|=0X30; DDRC|=0X30; // DDRD|=0XF7; }
void CH452_I2c_Start() { #ifdef USE_KEY DISABLE_INTERRUPT; //禁止鍵盤中斷,防止開始時(shí)被CH452中斷而進(jìn)入中斷服務(wù)程序中的START #endif CH452_SDA_SET; /*發(fā)送起始條件的數(shù)據(jù)信號(hào)*/ CH452_SCL_SET; mDelay1uS(); CH452_SDA_CLR; /*發(fā)送起始信號(hào)*/ mDelay1uS(); CH452_SCL_CLR; /*鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù) */ mDelay1uS(); } void CH452_I2c_Stop() { CH452_SDA_CLR; mDelay1uS(); CH452_SCL_SET; mDelay1uS(); CH452_SDA_SET; /*發(fā)送I2C總線結(jié)束信號(hào)*/ mDelay1uS(); #ifdef USE_KEY ENABLE_INTERRUPT; #endif } void CH452_I2c_WrByte(unsigned char c) //寫一個(gè)字節(jié)數(shù)據(jù) { unsigned char i; for(i=0;i!=8;i++) // 輸出8位數(shù)據(jù) { if(c&0x80) {CH452_SDA_SET;} else {CH452_SDA_CLR;} CH452_SCL_SET; c<<=1; mDelay1uS(); mDelay1uS(); CH452_SCL_CLR; mDelay1uS(); // DELAY_1US; } mDelay1uS(); CH452_SDA_SET; CH452_SCL_SET; // 接收應(yīng)答 mDelay1uS(); mDelay1uS(); CH452_SCL_CLR; mDelay1uS(); } unsigned char CH452_I2c_RdByte() //讀一個(gè)字節(jié)數(shù)據(jù) { unsigned char c,i; c=0; for(i=0;i!=8;i++) // 輸入8位數(shù)據(jù) { CH452_SDA_SET; CH452_SCL_SET; //////////////////////////// PORTC|=(1< DDRC&=~(1< //////////////////////////// mDelay1uS(); mDelay1uS(); c<<=1; if(CH452_SDA_IN) c|=0x01; // 輸入1位 /////////////////////////// DDRC|=(1< /////////////////////////// CH452_SCL_CLR; mDelay1uS(); // DELAY_1US; } mDelay1uS(); CH452_SDA_SET; CH452_SCL_SET; // 發(fā)出無效應(yīng)答 mDelay1uS(); mDelay1uS(); CH452_SCL_CLR; mDelay1uS(); return(c); } void CH452_Write(unsigned int command) //寫命令 { CH452_I2c_Start(); /*啟動(dòng)總線*/ #ifdef ENABLE_2_CH452 // 若有兩個(gè)CH452并連 CH452_I2c_WrByte(((unsigned char)(command>>7)&0x3E)|0x40); // CH452的ADDR=0時(shí) #else CH452_I2c_WrByte(((unsigned char)(command>>7)&0x3E)|0x60); // CH452的ADDR=1時(shí)(默認(rèn)) #endif CH452_I2c_WrByte((unsigned char)command); /*發(fā)送數(shù)據(jù)*/ CH452_I2c_Stop(); /*結(jié)束總線*/ }
void port_init(void) { PORTB = 0x00; PORTC = 0x00; //m103 output only DDRC = 0x00; PORTD = 0x00; DDRD = 0x00; }
void spi_init(){ DDRB |= 0x2c;//SCK-OUT,MISO-IN,MOSI-OUT,SS-OUT DDRD &=0XFB;//PD2-IN,鍵盤中斷引腳 SPCR = 0x73;//SPE=1,DORD=1(LSB FIRSET),MSTR=1,CPOL=CPOH=0,SPR0=SPR1=1 } void spi_send(unsigned short cData) { PORTB &=0xfb;//cs=0 mDelay1uS(); mDelay1uS(); cData =cData<<4; SPDR = cData&0xff; /* 等待傳輸結(jié)束 */ while(!(SPSR & (1< SPDR = (unsigned char)(cData>>8);; /* 等待傳輸結(jié)束 */ while(!(SPSR & (1< PORTB |=0x04;//cs=1 mDelay1uS(); mDelay1uS(); mDelay1uS(); mDelay1uS(); mDelay1uS(); mDelay1uS(); }
unsigned char spi_rec(void ) { unsigned char key,c; DDRB |= 0x2c;//SCK-OUT,MISO-IN,MOSI-OUT,SS-OUT SPCR = 0x53;//SPE=1,DORD=0(MSB FIRSET),MSTR=1,CPOL=CPOH=0,SPR0=SPR1=1 PORTB &=0xfb;//cs=0 mDelay1uS(); mDelay1uS(); SPDR = 0x0E; /* 等待傳輸結(jié)束 */ while(!(SPSR & (1< mDelay1uS(); mDelay1uS(); PORTB |=0x04;//cs=1 CH452_Write(0x0800|0X03); mDelay1uS(); mDelay1uS(); SPDR = 0x00;//接收數(shù)據(jù) /* 等待傳輸結(jié)束 */ while(!(SPSR & (1< mDelay1uS(); mDelay1uS(); key=SPDR; key=key>>1; DDRB |= 0x2c;//SCK-OUT,MISO-IN,MOSI-OUT,SS-OUT SPCR = 0x73;//SPE=1,DORD=1(LSB FIRSET),MSTR=1,CPOL=CPOH=0,SPR0=SPR1=1 mDelay1uS(); mDelay1uS(); mDelay1uS(); mDelay1uS(); return key; } void main(void){ unsigned int i=0; Delay50ms( ); Delay50ms( ); Delay50ms( ); Delay50ms( ); Delay50ms( ); Delay50ms( ); Delay50ms( ); port_init( ); init_CH452_IO(); CH452_Write(0X0401); CH452_Write(0x058C); spi_init( ); //初始化 spi_send(0x403); Delay50ms( ); spi_send(0x058C); Delay50ms( ); spi_send(0x800|0x01); Delay50ms( ); spi_send(0xc00|0x02); Delay50ms( ); spi_send(0xd00|0x05); CH452_Write(0x0900|0X07); while(1){ spi_send(0x403); Delay50ms( ); spi_send(0x058C); Delay50ms( ); CH452_Write(0x0800|0X01); if(CH452_WIRE==0){ //鍵盤,查詢方式 spi_send(0XA00|spi_rec()&0x0f); CH452_Write(0x0a00|spi_rec()&0x0f); spi_send(0XB00|(spi_rec()&0xf0)>>4); CH452_Write(0x0900|(spi_rec()&0xf0)>>4); } } }
中間有的延時(shí)不夠準(zhǔn)確,有的延時(shí)可以不需要,可以根據(jù)單片機(jī)的主頻來進(jìn)行調(diào)整,還需要說明的就是單片機(jī)的中斷引腳(判斷是否有鍵按下的中斷線)要和SPI的輸入引腳相連接