|
最近打算给大门外走廊增加几个人体红外热释电监控,上淘宝搜罗2.4G模块,想着买几个NRF24L01才发现价格都上去了。
好吧,你涨价我就用别的,现在国产IC便宜量又足,N76E003、CH55×都有了,我就不信找不到个2.4G的芯片。
逛了一圈,发现LT8920还不错,上某商城买几片,附上12M晶振,刚好包邮。
收到货翻开资料一看又傻眼,这数据手册太简单了!翻遍百度文库、Github终于搞定自动应答的发送和接收,各种艰辛按下不表。
把TSSOP16的芯片焊到TSSOP20转接板,然后面包板出动,插上杜邦线。天线就随便弄根导线顶着用。
淘宝找到的库是各种坑爹,GitHub也不靠谱。
最后在百度文库搜到了厂家技术支持的资料,才明白这芯片主要供货给遥控直升机玩具厂商。
而且这厂家技术人员还帮人看PCB!
更惊悚的是,这芯片可以用i2c,加上reset共3个控制管脚。。。。太省事了。但是我用惯了nRF24L01,还是用SPI吧。源码来了:
为了资持N76,我这次放出来的源码也是N76的。
首先是头文件,用法也写在头文件里了,看最后的注释:
- #ifndef N73E003_HEADERS
- #define N73E003_HEADERS
- #include "N76E003.h"
- #include "SFR_Macro.h"
- #include "Function_define.h"
- #include "Common.h"
- #include "Delay.h"
- #endif
- #define _DEBUG_LT8920
- #ifdef _DEBUG_LT8920
- void debugPrt(UINT8 data1);
- void debugPrtLn(UINT8 data1);
- void debugPrtStr(UINT8 * strPtr);
- #endif
- /*
- LT8920 nRF24 STM8S003F N76E003
- SPI SPI SPI SPI
- RESET csn GPIOA,GPIO_PIN_2 P17
- SS ce GPIOA,GPIO_PIN_1 P30
- */
- #define lt8920_delay_us(x) Timer3_Delay10us(x/20<1?1:x/20)
- #define lt8920_delay_ms(x) Timer3_Delay10us(x*100)
- #define _LT8920_GPIO_RST GPIOA,GPIO_PIN_2
- #define _LT8920_GPIO_SS GPIOA,GPIO_PIN_1
- #define _LT8920_RST_set lt8920_delay_us(10);P17=1
- #define _LT8920_RST_reset P17=0;lt8920_delay_us(10)
- #define _LT8920_SS_set lt8920_delay_us(10);P30=1
- #define _LT8920_SS_reset P30=0;lt8920_delay_us(10)
- #define Dummy_Byte 0xFF
- void LT8920_peri_init(void);
- UINT8 LT8920_SPI_transfer(UINT8 sendByte);
- void SPI_WriteReg(unsigned char addr, unsigned char H, unsigned char L);
- void SPI_ReadReg(unsigned char addr , unsigned char * regData);
- void LT8920_prt_reg(UINT8 regNum);
- void LT8920_init();
- void LT8920_startListening();
- UINT8 LT8920_waitPKT();
- UINT8 LT8920_recvData(UINT8 * buf2rcv);
- UINT8 LT8920_sendData(UINT8 * buf2send, UINT8 bufsize);
- /*
- //send example
- UINT8 data2send[32] = {0} ;
- UINT8 flag = 0 ;
- while(flag == 0 ){
- flag = LT8920_sendData( (UINT8 *)data2send , 32 ) ;
- }
- //recv example
- UINT8 data2rcv[32] = {0};
- UINT8 flag = 0 ;
- LT8920_startListening();
- LT8920_waitPKT();
- while(flag == 0){
- flag = LT8920_recvData( (UINT8 *)data2rcv ) ;
- }
- */
复制代码
然后是C文件:
- #include "lt8920.h"
- void LT8920_peri_init(void)
- {
- P07_PushPull_Mode;
- P07=1;
- P17_PushPull_Mode;
- P30_PushPull_Mode;
- set_P1SR_7;
- set_P3SR_0;
- P10_Quasi_Mode; // P10(SPCLK) Quasi mode
- set_P1SR_0;
- P00_Quasi_Mode; // P00 (MOSI) Quasi mode
- set_P0SR_0;
- P01_Quasi_Mode; // P22 (MISO) Quasi mode
- set_DISMODF; // SS General purpose I/O ( No Mode Fault )
- clr_SSOE;
- clr_LSBFE; // MSB first
- clr_CPOL; // The SPI clock is low in idle mode
- set_CPHA; // The data is sample on the second edge of SPI clock
- set_MSTR; // SPI in Master mode
- SPICLK_DIV2; // Select SPI clock
- set_SPIEN; // Enable SPI function
- clr_SPIF;
- }
- UINT8 LT8920_SPI_transfer(UINT8 sendByte){
- UINT8 rcvByte = 0 ;
-
- SPDR = sendByte ;
- //lt8920_delay_us(1);
- while(!(SPSR & SET_BIT7));
- clr_SPIF;
-
- rcvByte = SPDR ;
- return rcvByte ;
- }
- void SPI_WriteReg(UINT8 addr, UINT8 H, UINT8 L)
- {
- _LT8920_SS_reset;
- LT8920_SPI_transfer(addr);
- LT8920_SPI_transfer(H);
- LT8920_SPI_transfer(L);
- _LT8920_SS_set;
- }
- void SPI_ReadReg(UINT8 addr , UINT8 * regData){
- //reg[0] : regH
- //reg[1] : regL
- _LT8920_SS_reset;
- //lt8920_delay_us(1);
- addr |= 0x80; //when reading a Register,the Address should be added with 0x80.
- LT8920_SPI_transfer(addr);
- //lt8920_delay_us(1);
- regData[0] = LT8920_SPI_transfer(Dummy_Byte);
- //lt8920_delay_us(1);
- regData[1] = LT8920_SPI_transfer(Dummy_Byte);
- //lt8920_delay_us(1);
- _LT8920_SS_set;
- //lt8920_delay_us(1);
- }
- #ifdef _DEBUG_LT8920
-
- void debugPrt(UINT8 data1){
- UINT8 prtChar = '0' ;
-
- if(data1/16 < 10){
- prtChar += data1/16 ;
- }else{
- prtChar = data1/16-10 + 'A' ;
- }
- Send_Data_To_UART0(prtChar);
-
- if(data1%16 < 10){
- prtChar = '0' + data1%16 ;
- }else{
- prtChar = data1%16-10 + 'A' ;
- }
- Send_Data_To_UART0(prtChar);
- Send_Data_To_UART0(',');
- }
- void debugPrtLn(UINT8 data1){
- debugPrt(data1);
- Send_Data_To_UART0('\r');
- Send_Data_To_UART0('\n');
- }
- void debugPrtStr(UINT8 * strPtr){
- UINT8 ii = 0 ;
- for(; ii < 250 && strPtr[ii] != '\0'; ii++){
- Send_Data_To_UART0(strPtr[ii]);
- }
- }
- #endif
- void LT8920_prt_reg(UINT8 regNum){
- UINT8 regData[2] = {0};
- UINT8 str2prt[] = "print reg " ;
- SPI_ReadReg(regNum , (UINT8 *)regData) ;
-
- #ifdef _DEBUG_LT8920
- debugPrtStr( (UINT8 * )str2prt ) ;
- debugPrt(regNum) ;
- Send_Data_To_UART0(':');
- debugPrt(regData[0]);
- debugPrtLn(regData[1]);
- #endif
- }
- void LT8920_init(){ //LT8920 init start
- UINT8 regData[2] = {0} ;
- //SPI_LT8920_Init();
- _LT8920_RST_reset;//LT8920_RST_LOW();
- lt8920_delay_ms(2);
- _LT8920_RST_set;//LT8920_RST_HIGH();
- lt8920_delay_ms(5);
- // LT8920_PKT_OUT =1;
- //SPI_WriteReg( 0, 0x6f, 0xef );
- SPI_WriteReg( 0, 0x6f, 0xe0 );
- SPI_WriteReg( 1, 0x56, 0x81 );
- SPI_WriteReg( 2, 0x66, 0x17 );
- SPI_WriteReg( 4, 0x9c, 0xc9 );
- SPI_WriteReg( 5, 0x66, 0x37 );
- //SPI_WriteReg( 7, 0x00, 0x00 ); //channel is 2402Mhz //改频道写这里
- SPI_WriteReg( 8, 0x6c, 0x90 );
- //SPI_WriteReg( 9, 0x18, 0x40 ); //PA Power
- SPI_WriteReg( 9, 0x48, 0x40 ); //PA Power try max power !!!!
-
- SPI_WriteReg(10, 0x7F , 0xfd) ; //Crystal enable
- /*
- check write result
- SPI_ReadReg( 10 , (UINT8 *)regData ) ;
- while( regData[0] != 0x7F || regData[1] != 0xfd ){
- SPI_WriteReg(10, 0x7F , 0xfd) ;
- SPI_ReadReg(10 , (UINT8 *)regData ) ;
- }*/
- SPI_WriteReg(11, 0x00, 0x08 ); //RSSI enable
- SPI_WriteReg(12, 0x00, 0x00 );
- SPI_WriteReg(13, 0x48, 0xbd );
- SPI_WriteReg(22, 0x00, 0xff );
- SPI_WriteReg(23, 0x80, 0x05 );
- SPI_WriteReg(24, 0x00, 0x67 );
- SPI_WriteReg(25, 0x16, 0x59 );
- SPI_WriteReg(26, 0x19, 0xe0 );
- SPI_WriteReg(27, 0x13, 0x00 );
- SPI_WriteReg(28, 0x18, 0x00 );
- // reg 32 [15:13]preamble len [12:11]syncword len [10:8]trailer len [7:6]dataPacketType [3:1]brclk
- // 010 3bytes 01 32bites 000 4bits 00 NRZ law data low
- SPI_WriteReg(32, 0x48, 0x00 ); //8920在62.5kbps下同步头只能是32或16bit
- SPI_WriteReg(33, 0x3f, 0xc7 ); //packet sequence
- SPI_WriteReg(34, 0x20, 0x00 ); //packet sequence
- //SPI_WriteReg(35, 0x05, 0x00 ); //auto ack and reties 重发次数4次
- SPI_WriteReg(35, 0x0F, 0x00 ); //auto ack and reties 重发次数15次
- SPI_WriteReg(36, 0x03, 0x80 ); //unique sync word 1
- SPI_WriteReg(37, 0x03, 0x80 ); //2
- SPI_WriteReg(38, 0x5a, 0x5a ); //3
- SPI_WriteReg(39, 0x03, 0x80 ); //4
- SPI_WriteReg(40, 0x44, 0x01 ); //FIFO flag 2102??
- //reg 41 [15]crc_on [13]pkg_len_en [12]fw_term_tx [11]auto_ack
- // 1 crc 1 1 1
- SPI_WriteReg(41, 0xb8, 0x00 ); //CRC is ON; scramble is OFF; AUTO_ACK is ON 0000??
- SPI_WriteReg(42, 0xfd, 0xb0 ); //等待RX_ACK时间 176us
- SPI_WriteReg(43, 0x00, 0x0f ); //scan rssi
- //reg 44 [15:8]data rate
- // 01:1M 10:62k5
- SPI_WriteReg(44, 0x10, 0x00 ); //data rate 62.5k
- SPI_WriteReg(45, 0x05, 0x52 ); //
- SPI_WriteReg(50, 0x00, 0x00 );
- lt8920_delay_ms(100);
- }
- void LT8920_startListening(){
- SPI_WriteReg(7, 0x00, 0x00); //设定模式 //接收的频道是第3个参数的0~6共7位比特
- SPI_WriteReg(52, 0x80, 0x80); //清空 RXTX
- SPI_WriteReg(7, 0x00, 0x80); //接收模式
- lt8920_delay_us(20);
- }
- UINT8 LT8920_waitPKT(){ //相当于发送完成、接收成功的终端
- //wait PKT
- //send done or recv done
- UINT8 regData[2] = {0};
- SPI_ReadReg(48,(UINT8 * )regData);
- while( (regData[1] & 0x40) <= 0 ){
- SPI_ReadReg(48 ,(UINT8 * )regData );
- }
- return 0 ;
- }
- UINT8 LT8920_recvData(UINT8 * buf2rcv){
- //return len of data when success
- //return 0 when fail
- UINT8 regData[2] = {0} ;
- UINT8 idx = 0 ;
- UINT8 len ;
- SPI_ReadReg(50, (UINT8 *)regData );
- len = regData[0] ;
- while(idx +1 < len){
- SPI_ReadReg(50, (UINT8 *)regData );
- buf2rcv[idx++]=regData[0] ;
- buf2rcv[idx++]=regData[1] ;
- if( idx >= 64) break ;
- }
- SPI_ReadReg(48, (UINT8 *)regData ); //test CRC
- if(( regData[0] &0x80)==0){//检查CRC是否正确
- //CRC right
- //UINT8 str2prt[] = "CRC correct .. " ;
- //debugPrtStr( (UINT8 * )str2prt ) ;
- //for(UINT8 ii = 0 ; ii < 31 ; ii ++ )debugPrt( data2rcv[ii] ) ;
- //debugPrtLn(data2rcv[32]) ;
- return len ;
- }else{
- //UINT8 str2prt[] = "CRC fail .. " ;
- //debugPrtStr( (UINT8 * )str2prt ) ;
- //for(UINT8 ii = 0 ; ii < 31 ; ii ++ )debugPrt( data2rcv[ii] ) ;
- //debugPrtLn(data2rcv[32]) ;
- return 0 ;
- }
- }
- UINT8 LT8920_sendData(UINT8 * buf2send, UINT8 bufsize){
- //return 1 when success
- //return 0 when fail
- UINT8 idx ;
- UINT8 regData[2] ={0};
- UINT8 pos ;
- SPI_WriteReg(7, 0x00, 0x00); //设定模式
- SPI_WriteReg(52, 0x80, 0x80); //清空接收、发送FIFO数据
- //SPI_WriteReg(50, 2,0); //发送数据长度
-
- pos = 0 ;
- //SPI_WriteReg(50 , 32 , data2send[pos++]) ;
- SPI_WriteReg(50 , 32 , 0 ) ; //发送32个字节,先把长度写在第2个参数
- for(idx = 0 ;idx < bufsize / 2 ; idx ++ ) { //然后把32个字节的数据都传进去
- SPI_WriteReg(50 , buf2send[idx*2] , buf2send[idx*2+1] ) ;
- }
- //LT8920_prt_reg(7);
- //SPI_WriteReg(7, 0x01, 0x08); //发送
- SPI_WriteReg(7, 0x01, 0x00);
- //LT8920_prt_reg(7);
-
- //wait until PKT_FLAG become 1
- LT8920_waitPKT();
-
- SPI_ReadReg(52 , (UINT8 *)regData );
- //LT8920_prt_reg(52);
- //reg 52 [13:8]FIFO_WR_PTR [5:0]FIFO_RD_PTR
- if( ( regData[0] & 0x3F) == 0 ){ //收到对方的自动应答后,返回1
- //auto ack received
- return 1 ;
- }
- return 0 ;
- }
复制代码
调通后打开久违的AD10画板,拼板,发给PCB厂家。
说个插曲,某大厂业务大概是嫌我抠,我同款拼板发过去,楞是给我加上50费用。找业务一通问,又等了大半天,业务大妈晃悠悠发个图给我,要我把尺寸改大了再批。改完重新上传,审单的又说这个那个费,仅比刚才便宜1元!:huffy:业务大妈和审单大爷合伙欺负人啊这是。说好的特价原来只存在于网站首页宣传栏~厂大欺人!
本来PCB打样也没多大技术含量吧,贵厂宣传做得好客户多就傲娇,那我何必给自己找不痛快,赶紧论坛里找一家。
同款拼板不加钱,10×10打5片也是30,一样包邮,做出来质量也不错,上图给大伙瞧瞧
拼板,1.5×2的小板,拼出来是35块一大板,一共175块:lol:。哪位大兄弟有兴趣可以私信我,送一些。
焊板,插上测试。这个芯片还有个好处,外围只需要2个电容、1个晶振和1根任意长度的导线。对的,不需要画PCB天线。
对比我之前的nRF24L01芯片,LT8920非常好伺候。传输距离也差不多。我画板还特意画成nRF24模块引脚兼容。
成品图片:
简单地说这个芯片可以替代nRF24L01,只是程序要调整。
好了,感谢大家看完我的罗嗦长文。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
打赏
-
查看全部打赏
|