前两天接触瑞萨单片机,刚开始他的代码生成器给人眼前一亮,感觉单片机就应该这样。操作底层寄存器这种无聊的工作,就不应该让程序员去做,可能这也是单片机的一个发展趋势吧,像stm32一样有一些库函数,让人从繁琐的寄存器配置工作中解放出来,把更多的经历花费在软件设计上。不过瑞萨的那个CubeSuite +的代码错误定位真是让人受不了。根本找不到错误在哪一行,希望下个版本有所改善。
CC1100寄存器0x09中的版本号手册上说是0x04,但实际读了几个片子,都是0x14,这一点用读版本号来调试时要注意一下。
引脚分配:
#define GDO0 P1.4 //Pin42 input #define GDO2 P1.3 //Pin43 input #define MISO P1.2 //Pin44 input #define MOSI P1.1 //Pin45 output #define SCK P1.0 //Pin46 output #define CSN P1.5 //Pin41 output
CC1100代码从51移植过来,这个工作并不复杂,主要是移植这SpiTxRxByte()这个函数,这个函数移植之后。你可以读写CC1100的地址寄存器,来试试这个函数是否正确。当然这样并没有使用瑞萨单片机的内置SPI接口,如果使用的话,SPI配置的Specification of data timing 一栏要使用Type4模式。
#define GDO0 P1.4 #define GDO2 P1.3 #define MISO P1.2 #define MOSI P1.1 #define SCK P1.0 #define CSN P1.5 //***************************************************************************************** //SPI发送接收函数,输入为要发送的数据,输出为接收到的数据。 //***************************************************************************************** uint8_t SpiTxRxByte(uint8_t dat) { uint8_t i,temp; temp = 0; SCK = 0; for(i=0; i<8; i++) { if(dat & 0x80) { MOSI = 1; } else MOSI = 0; dat <<= 1; SCK = 1; NOP(); NOP(); temp <<= 1; if(MISO)temp++; SCK = 0; NOP(); NOP(); } return temp; }
测试时候:可以向用下面两行CC1100的地址寄存器0x09,具体你可以下载工程看一下,写入一个数值,再读出来以测试,SPI接口函数是否能有CC1100正常,通信如果正常通信,那么就成功一半。当然调试的时候能有一个已经能正常收发的模块是最好了。
halSpiWriteReg(0x09, 0x03); version = halSpiReadReg(0x09);
之后就是测试收发是否正常。就是测试这个函数halRfReceivePacket()和 halRfSendPacket() 。然后就可以正常使用了。
halRfReceivePacket(); void halRfSendPacket(uint8_t *txBuffer, uint8_t size) ; uint8_t halRfReceivePacket(uint8_t *rxBuffer, uint8_t *length) ;
下面是整理的.c和.h文件,在CubeSuite +中直接加进去使用。
主要是使用这三个函数。
void initCC1100(void);//初始化CC1100。 void halRfSendPacket(uint8_t *txBuffer, uint8_t size) ;//发送txbuffer中的内容,size为长度。 uint8_t halRfReceivePacket(uint8_t *rxBuffer, uint8_t *length) ;//接收数据放入,rxbuffer中,length为接收到的数据长度。
//CC1100.h #ifndef _CC1100_H_ #define _CC1100_H_ /* Start user code for function. Do not edit comment generated here */ //#include "r_cg_port.h" #include "r_cg_macrodriver.h" #define GDO0 P1.4 #define GDO2 P1.3 #define MISO P1.2 #define MOSI P1.1 #define SCK P1.0 #define CSN P1.5 #define WRITE_BURST 0x40 #define READ_SINGLE 0x80 #define READ_BURST 0xC0 #define BYTES_IN_RXFIFO 0x7F #define CRC_OK 0x80 #define CCxxx0_IOCFG2 0x00 // GDO2 output pin configuration #define CCxxx0_IOCFG1 0x01 // GDO1 output pin configuration #define CCxxx0_IOCFG0 0x02 // GDO0 output pin configuration #define CCxxx0_FIFOTHR 0x03 // RX FIFO and TX FIFO thresholds #define CCxxx0_SYNC1 0x04 // Sync word, high uint8_t #define CCxxx0_SYNC0 0x05 // Sync word, low uint8_t #define CCxxx0_PKTLEN 0x06 // Packet length #define CCxxx0_PKTCTRL1 0x07 // Packet automation control #define CCxxx0_PKTCTRL0 0x08 // Packet automation control #define CCxxx0_ADDR 0x09 // Device address #define CCxxx0_CHANNR 0x0A // Channel number #define CCxxx0_FSCTRL1 0x0B // Frequency synthesizer control #define CCxxx0_FSCTRL0 0x0C // Frequency synthesizer control #define CCxxx0_FREQ2 0x0D // Frequency control word, high uint8_t #define CCxxx0_FREQ1 0x0E // Frequency control word, middle uint8_t #define CCxxx0_FREQ0 0x0F // Frequency control word, low uint8_t #define CCxxx0_MDMCFG4 0x10 // Modem configuration #define CCxxx0_MDMCFG3 0x11 // Modem configuration #define CCxxx0_MDMCFG2 0x12 // Modem configuration #define CCxxx0_MDMCFG1 0x13 // Modem configuration #define CCxxx0_MDMCFG0 0x14 // Modem configuration #define CCxxx0_DEVIATN 0x15 // Modem deviation setting #define CCxxx0_MCSM2 0x16 // Main Radio Control State Machine configuration #define CCxxx0_MCSM1 0x17 // Main Radio Control State Machine configuration #define CCxxx0_MCSM0 0x18 // Main Radio Control State Machine configuration #define CCxxx0_FOCCFG 0x19 // Frequency Offset Compensation configuration #define CCxxx0_BSCFG 0x1A // Bit Synchronization configuration #define CCxxx0_AGCCTRL2 0x1B // AGC control #define CCxxx0_AGCCTRL1 0x1C // AGC control #define CCxxx0_AGCCTRL0 0x1D // AGC control #define CCxxx0_WOREVT1 0x1E // High uint8_t Event 0 timeout #define CCxxx0_WOREVT0 0x1F // Low uint8_t Event 0 timeout #define CCxxx0_WORCTRL 0x20 // Wake On Radio control #define CCxxx0_FREND1 0x21 // Front end RX configuration #define CCxxx0_FREND0 0x22 // Front end TX configuration #define CCxxx0_FSCAL3 0x23 // Frequency synthesizer calibration #define CCxxx0_FSCAL2 0x24 // Frequency synthesizer calibration #define CCxxx0_FSCAL1 0x25 // Frequency synthesizer calibration #define CCxxx0_FSCAL0 0x26 // Frequency synthesizer calibration #define CCxxx0_RCCTRL1 0x27 // RC oscillator configuration #define CCxxx0_RCCTRL0 0x28 // RC oscillator configuration #define CCxxx0_FSTEST 0x29 // Frequency synthesizer calibration control #define CCxxx0_PTEST 0x2A // Production test #define CCxxx0_AGCTEST 0x2B // AGC test #define CCxxx0_TEST2 0x2C // Various test settings #define CCxxx0_TEST1 0x2D // Various test settings #define CCxxx0_TEST0 0x2E // Various test settings // Strobe commands #define CCxxx0_SRES 0x30 // Reset chip. #define CCxxx0_SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). // If in RX/TX: Go to a wait state where only the synthesizer is // running (for quick RX / TX turnaround). #define CCxxx0_SXOFF 0x32 // Turn off crystal oscillator. #define CCxxx0_SCAL 0x33 // Calibrate frequency synthesizer and turn it off // (enables quick start). #define CCxxx0_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and // MCSM0.FS_AUTOCAL=1. #define CCxxx0_STX 0x35 // In IDLE state: Enable TX. Perform calibration first if // MCSM0.FS_AUTOCAL=1. If in RX state and CCA is enabled: // Only go to TX if channel is clear. #define CCxxx0_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit // Wake-On-Radio mode if applicable. #define CCxxx0_SAFC 0x37 // Perform AFC adjustment of the frequency synthesizer #define CCxxx0_SWOR 0x38 // Start automatic RX polling sequence (Wake-on-Radio) #define CCxxx0_SPWD 0x39 // Enter power down mode when CSn goes high. #define CCxxx0_SFRX 0x3A // Flush the RX FIFO buffer. #define CCxxx0_SFTX 0x3B // Flush the TX FIFO buffer. #define CCxxx0_SWORRST 0x3C // Reset real time clock. #define CCxxx0_SNOP 0x3D // No operation. May be used to pad strobe commands to two // uint8_ts for simpler software. #define CCxxx0_PARTNUM 0x30 #define CCxxx0_VERSION 0x31 #define CCxxx0_FREQEST 0x32 #define CCxxx0_LQI 0x33 #define CCxxx0_RSSI 0x34 #define CCxxx0_MARCSTATE 0x35 #define CCxxx0_WORTIME1 0x36 #define CCxxx0_WORTIME0 0x37 #define CCxxx0_PKTSTATUS 0x38 #define CCxxx0_VCO_VC_DAC 0x39 #define CCxxx0_TXBYTES 0x3A #define CCxxx0_RXBYTES 0x3B #define CCxxx0_PATABLE 0x3E #define CCxxx0_TXFIFO 0x3F #define CCxxx0_RXFIFO 0x3F struct S_RF_SETTINGS { uint8_t FSCTRL2; uint8_t FSCTRL1; // Frequency synthesizer control. uint8_t FSCTRL0; // Frequency synthesizer control. uint8_t FREQ2; // Frequency control word, high uint8_t. uint8_t FREQ1; // Frequency control word, middle uint8_t. uint8_t FREQ0; // Frequency control word, low uint8_t. uint8_t MDMCFG4; // Modem configuration. uint8_t MDMCFG3; // Modem configuration. uint8_t MDMCFG2; // Modem configuration. uint8_t MDMCFG1; // Modem configuration. uint8_t MDMCFG0; // Modem configuration. uint8_t CHANNR; // Channel number. uint8_t DEVIATN; // Modem deviation setting (when FSK modulation is enabled). uint8_t FREND1; // Front end RX configuration. uint8_t FREND0; // Front end RX configuration. uint8_t MCSM0; // Main Radio Control State Machine configuration. uint8_t FOCCFG; // Frequency Offset Compensation Configuration. uint8_t BSCFG; // Bit synchronization Configuration. uint8_t AGCCTRL2; // AGC control. uint8_t AGCCTRL1; // AGC control. uint8_t AGCCTRL0; // AGC control. uint8_t FSCAL3; // Frequency synthesizer calibration. uint8_t FSCAL2; // Frequency synthesizer calibration. uint8_t FSCAL1; // Frequency synthesizer calibration. uint8_t FSCAL0; // Frequency synthesizer calibration. uint8_t FSTEST; // Frequency synthesizer calibration control uint8_t TEST2; // Various test settings. uint8_t TEST1; // Various test settings. uint8_t TEST0; // Various test settings. uint8_t IOCFG2; // GDO2 output pin configuration uint8_t IOCFG0; // GDO0 output pin configuration uint8_t PKTCTRL1; // Packet automation control. uint8_t PKTCTRL0; // Packet automation control. uint8_t ADDR; // Device address. uint8_t PKTLEN; // Packet length. }; void delay(unsigned int s); void halWait(uint16_t timeout); void SpiInit(void); void CpuInit(void); void RESET_CC1100(void); void POWER_UP_RESET_CC1100(void); void halSpiWriteReg(uint8_t addr, uint8_t value); void halSpiWriteBurstReg(uint8_t addr, uint8_t *buffer, uint8_t count); void halSpiStrobe(uint8_t strobe); uint8_t halSpiReadReg(uint8_t addr); void halSpiReadBurstReg(uint8_t addr, uint8_t *buffer, uint8_t count) ; uint8_t halSpiReadStatus(uint8_t addr) ; void halRfWriteRfSettings(void) ; void setRxMode(void); /**************************************************************/ void initCC1100(void); void halRfSendPacket(uint8_t *txBuffer, uint8_t size) ; uint8_t halRfReceivePacket(uint8_t *rxBuffer, uint8_t *length) ; /***************************************************************/ /* End user code. Do not edit comment generated here */ #endif
//CC1100.c #include "CC1100.h" /* Start user code for adding. Do not edit comment generated here */ uint8_t PaTabel[8] = {0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60}; uint8_t SpiTxRxByte(uint8_t dat) { uint8_t i,temp; temp = 0; SCK = 0; for(i=0; i<8; i++) { if(dat & 0x80) { MOSI = 1; } else MOSI = 0; dat <<= 1; SCK = 1; NOP(); NOP(); temp <<= 1; if(MISO)temp++; SCK = 0; NOP(); NOP(); } return temp; } const struct S_RF_SETTINGS rfSettings = { 0x00, 0x08, 0x00, // FSCTRL0 Frequency synthesizer control. 0x10, // FREQ2 Frequency control word, high byte. 0xA7, // FREQ1 Frequency control word, middle byte. 0x62, // FREQ0 Frequency control word, low byte. 0x5B, // MDMCFG4 Modem configuration. 0xF8, // MDMCFG3 Modem configuration. 0x03, // MDMCFG2 Modem configuration. 0x22, // MDMCFG1 Modem configuration. 0xF8, // MDMCFG0 Modem configuration. 0x01, // CHANNR Channel number. 0x47, // DEVIATN Modem deviation setting (when FSK modulation is enabled). 0xB6, // FREND1 Front end RX configuration. 0x10, // FREND0 Front end RX configuration. 0x18, // MCSM0 Main Radio Control State Machine configuration. 0x1D, // FOCCFG Frequency Offset Compensation Configuration. 0x1C, // BSCFG Bit synchronization Configuration. 0xC7, // AGCCTRL2 AGC control. 0x00, // AGCCTRL1 AGC control. 0xB2, // AGCCTRL0 AGC control. 0xEA, // FSCAL3 Frequency synthesizer calibration. 0x2A, // FSCAL2 Frequency synthesizer calibration. 0x00, // FSCAL1 Frequency synthesizer calibration. 0x11, // FSCAL0 Frequency synthesizer calibration. 0x59, // FSTEST Frequency synthesizer calibration. 0x81, // TEST2 Various test settings. 0x35, // TEST1 Various test settings. 0x09, // TEST0 Various test settings. 0x0B, // IOCFG2 GDO2 output pin configuration. 0x06, // IOCFG0D GDO0 output pin configuration. Refer to SmartRF?Studio User Manual for detailed pseudo register explanation. 0x04, // PKTCTRL1 Packet automation control. 0x05, // PKTCTRL0 Packet automation control. 0x00, // ADDR Device address. 0x0c // PKTLEN Packet length. }; static void delay(unsigned int s) { unsigned int i; for(i=0; i<s; i++); for(i=0; i<s; i++); } void halWait(uint16_t timeout) { do { NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); } while (--timeout); } void SpiInit(void) { CSN=0; SCK=0; CSN=1; } void CpuInit(void) { SpiInit(); delay(5000); } void RESET_CC1100(void) { CSN = 0; while (MISO); SpiTxRxByte(CCxxx0_SRES); while (MISO); CSN = 1; } void POWER_UP_RESET_CC1100(void) { CSN = 1; halWait(1); CSN = 0; halWait(1); CSN = 1; halWait(41); RESET_CC1100(); } void halSpiWriteReg(uint8_t addr, uint8_t value) { CSN = 0; while (MISO); SpiTxRxByte(addr); SpiTxRxByte(value); CSN = 1; } void halSpiWriteBurstReg(uint8_t addr, uint8_t *buffer, uint8_t count) { uint8_t i, temp; temp = addr | WRITE_BURST; CSN = 0; while (MISO); SpiTxRxByte(temp); for (i = 0; i < count; i++) { SpiTxRxByte(buffer[i]); } CSN = 1; } void halSpiStrobe(uint8_t strobe) { CSN = 0; while (MISO); SpiTxRxByte(strobe); CSN = 1; } uint8_t halSpiReadReg(uint8_t addr) { uint8_t temp, value; temp = addr|READ_SINGLE; CSN = 0; while (MISO); SpiTxRxByte(temp); value = SpiTxRxByte(0); CSN = 1; return value; } void halSpiReadBurstReg(uint8_t addr, uint8_t *buffer, uint8_t count) { uint8_t i,temp; temp = addr | READ_BURST; CSN = 0; while (MISO); SpiTxRxByte(temp); for (i = 0; i < count; i++) { buffer[i] = SpiTxRxByte(0); } CSN = 1; } uint8_t halSpiReadStatus(uint8_t addr) { uint8_t value,temp; temp = addr | READ_BURST; CSN = 0; while (MISO); SpiTxRxByte(temp); value = SpiTxRxByte(0); CSN = 1; return value; } void halRfWriteRfSettings(void) { halSpiWriteReg(CCxxx0_FSCTRL0, rfSettings.FSCTRL2); // Write register settings halSpiWriteReg(CCxxx0_FSCTRL1, rfSettings.FSCTRL1); halSpiWriteReg(CCxxx0_FSCTRL0, rfSettings.FSCTRL0); halSpiWriteReg(CCxxx0_FREQ2, rfSettings.FREQ2); halSpiWriteReg(CCxxx0_FREQ1, rfSettings.FREQ1); halSpiWriteReg(CCxxx0_FREQ0, rfSettings.FREQ0); halSpiWriteReg(CCxxx0_MDMCFG4, rfSettings.MDMCFG4); halSpiWriteReg(CCxxx0_MDMCFG3, rfSettings.MDMCFG3); halSpiWriteReg(CCxxx0_MDMCFG2, rfSettings.MDMCFG2); halSpiWriteReg(CCxxx0_MDMCFG1, rfSettings.MDMCFG1); halSpiWriteReg(CCxxx0_MDMCFG0, rfSettings.MDMCFG0); halSpiWriteReg(CCxxx0_CHANNR, rfSettings.CHANNR); halSpiWriteReg(CCxxx0_DEVIATN, rfSettings.DEVIATN); halSpiWriteReg(CCxxx0_FREND1, rfSettings.FREND1); halSpiWriteReg(CCxxx0_FREND0, rfSettings.FREND0); halSpiWriteReg(CCxxx0_MCSM0 , rfSettings.MCSM0 ); halSpiWriteReg(CCxxx0_FOCCFG, rfSettings.FOCCFG); halSpiWriteReg(CCxxx0_BSCFG, rfSettings.BSCFG); halSpiWriteReg(CCxxx0_AGCCTRL2, rfSettings.AGCCTRL2); halSpiWriteReg(CCxxx0_AGCCTRL1, rfSettings.AGCCTRL1); halSpiWriteReg(CCxxx0_AGCCTRL0, rfSettings.AGCCTRL0); halSpiWriteReg(CCxxx0_FSCAL3, rfSettings.FSCAL3); halSpiWriteReg(CCxxx0_FSCAL2, rfSettings.FSCAL2); halSpiWriteReg(CCxxx0_FSCAL1, rfSettings.FSCAL1); halSpiWriteReg(CCxxx0_FSCAL0, rfSettings.FSCAL0); halSpiWriteReg(CCxxx0_FSTEST, rfSettings.FSTEST); halSpiWriteReg(CCxxx0_TEST2, rfSettings.TEST2); halSpiWriteReg(CCxxx0_TEST1, rfSettings.TEST1); halSpiWriteReg(CCxxx0_TEST0, rfSettings.TEST0); halSpiWriteReg(CCxxx0_IOCFG2, rfSettings.IOCFG2); halSpiWriteReg(CCxxx0_IOCFG0, rfSettings.IOCFG0); halSpiWriteReg(CCxxx0_PKTCTRL1, rfSettings.PKTCTRL1); halSpiWriteReg(CCxxx0_PKTCTRL0, rfSettings.PKTCTRL0); halSpiWriteReg(CCxxx0_ADDR, rfSettings.ADDR); halSpiWriteReg(CCxxx0_PKTLEN, rfSettings.PKTLEN); } void halRfSendPacket(uint8_t *txBuffer, uint8_t size) { halSpiWriteReg(CCxxx0_TXFIFO, size); halSpiWriteBurstReg(CCxxx0_TXFIFO, txBuffer, size); halSpiStrobe(CCxxx0_STX); // Wait for GDO0 to be set -> sync transmitted while (!GDO0); // Wait for GDO0 to be cleared -> end of packet while (GDO0); halSpiStrobe(CCxxx0_SFTX); } void setRxMode(void) { halSpiStrobe(CCxxx0_SRX); } uint8_t halRfReceivePacket(uint8_t *rxBuffer, uint8_t *length) { uint8_t status[2]; uint8_t packetLength; uint8_t i=(*length)*4; halSpiStrobe(CCxxx0_SRX); //delay(5); //while (!GDO1); //while (GDO1); delay(2); while (GDO0) { delay(2); --i; if(i<1) return 0; } if ((halSpiReadStatus(CCxxx0_RXBYTES) & BYTES_IN_RXFIFO)) { packetLength = halSpiReadReg(CCxxx0_RXFIFO); if (packetLength <= *length) { halSpiReadBurstReg(CCxxx0_RXFIFO, rxBuffer, packetLength); *length = packetLength; // Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI) halSpiReadBurstReg(CCxxx0_RXFIFO, status, 2); halSpiStrobe(CCxxx0_SFRX); return (status[1] & CRC_OK); } else { *length = packetLength; halSpiStrobe(CCxxx0_SFRX); return 0; } } else return 0; } void initCC1100(void) { CpuInit(); POWER_UP_RESET_CC1100(); halRfWriteRfSettings(); halSpiWriteBurstReg(CCxxx0_PATABLE, PaTabel, 8); } /* End user code. Do not edit comment generated here */
下面是CC1100的资料,和移植好的瑞萨R5F100LE cubesuite+工程。移植的函数主要在r_cg_port.h 和r_cg_port_user.c中对比keil的工程文件,可以发现要移植的关键。
和被移植的51工程,51工程中有较详细的注释。cubesuite + 不支持中文所以没写什么注释。
用瑞萨单片R5F100LE使用无线模块CC1100代码工程链接
CC1100的被移植keil工程和资料