我用的单片机是C8051,使用硬件SPI三线主方式与CH452连接
三线主方式指的是单片机的SPI方式,用一个GPIO连接CH452的LOAD
CH452的4线接口不是SPI接口
CH452的4线接口不是SPI接口?不是部分兼容吗?我就硬要往SPI总线上挂!
不能往硬件SPI上面挂的。例子程序你可以下载CH372EV。ZIP,里面有451的4线制的例子程序
可以用SPI的,写CH45X命令的步骤如下 1.原始输入数据为12位,左移4位后变成16位(因为SPI数据位总是8个倍数) 2.设置SPI为方式0(或方式3),CPOL=0,CPHA=0,低位在前LSB,产生LOAD片选低电平 3.SPI输出一个字节,先是16位的低字节 4.SPI输出一个字节,再是16位的高字节 5.结束LOAD片选 读CH45X的命令,也就是读键盘命令的步骤如下 1.设置SPI为方式0,CPOL=0,CPHA=0,高位在前MSB,产生LOAD片选低电平 2.SPI输出一个字节,数据是0EH或者0FEH 3.结束LOAD片选 4.SPI输入一个字节,该数据作为无符号数右移一位后就是键盘码
这是一个硬件SPI和451相连接的例子程序,你可以参考,单片机是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( ) /* 至少延时1uS,根据单片机主频调整 */ { 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; //禁止键盘中断,防止开始时被CH452中断而进入中断服务程序中的START #endif CH452_SDA_SET; /*发送起始条件的数据信号*/ CH452_SCL_SET; mDelay1uS(); CH452_SDA_CLR; /*发送起始信号*/ mDelay1uS(); CH452_SCL_CLR; /*钳住I2C总线,准备发送或接收数据 */ mDelay1uS(); } void CH452_I2c_Stop() { CH452_SDA_CLR; mDelay1uS(); CH452_SCL_SET; mDelay1uS(); CH452_SDA_SET; /*发送I2C总线结束信号*/ mDelay1uS(); #ifdef USE_KEY ENABLE_INTERRUPT; #endif } void CH452_I2c_WrByte(unsigned char c) //写一个字节数据 { unsigned char i; for(i=0;i!=8;i++) // 输出8位数据 { 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; // 接收应答 mDelay1uS(); mDelay1uS(); CH452_SCL_CLR; mDelay1uS(); } unsigned char CH452_I2c_RdByte() //读一个字节数据 { unsigned char c,i; c=0; for(i=0;i!=8;i++) // 输入8位数据 { 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; // 发出无效应答 mDelay1uS(); mDelay1uS(); CH452_SCL_CLR; mDelay1uS(); return(c); } void CH452_Write(unsigned int command) //写命令 { CH452_I2c_Start(); /*启动总线*/ #ifdef ENABLE_2_CH452 // 若有两个CH452并连 CH452_I2c_WrByte(((unsigned char)(command>>7)&0x3E)|0x40); // CH452的ADDR=0时 #else CH452_I2c_WrByte(((unsigned char)(command>>7)&0x3E)|0x60); // CH452的ADDR=1时(默认) #endif CH452_I2c_WrByte((unsigned char)command); /*发送数据*/ CH452_I2c_Stop(); /*结束总线*/ }
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; /* 等待传输结束 */ while(!(SPSR & (1< SPDR = (unsigned char)(cData>>8);; /* 等待传输结束 */ 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; /* 等待传输结束 */ while(!(SPSR & (1< mDelay1uS(); mDelay1uS(); PORTB |=0x04;//cs=1 CH452_Write(0x0800|0X03); mDelay1uS(); mDelay1uS(); SPDR = 0x00;//接收数据 /* 等待传输结束 */ 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); } } }
中间有的延时不够准确,有的延时可以不需要,可以根据单片机的主频来进行调整,还需要说明的就是单片机的中断引脚(判断是否有键按下的中断线)要和SPI的输入引脚相连接