RISC-V MCU开发(二):Si24R1 通信模式调试

网友投稿 309 2022-11-23

RISC-V MCU开发(二):Si24R1 通信模式调试

目的

实现过程:

在IDE里新建项目后,都会包含CLIC_Init()和System_Clock_Init()两个函数。中断向量表初始化,系统中断初始化,用户无需关心。系统时钟初始化函数中,可以方便的选中时钟源、时钟分频系数、外设时钟使能和RC频率选择。

int main(void){ ///----System Init --------------------------------------------------------------------------------------------- CLIC_Init();//中断向量表初始化 System_Clock_Init();//系统时钟初始化void System_Clock_Init(void)//系统时钟初始化{ //时钟源开关 CMU->SRC_EN = 1<<1 //RCOSC bit[1]:0-off, 1-on |1<<0; //crystal bit[0]:0-off, 1-on //外设和内核时钟来源选择 CMU->CLK_SEL = 1<<2 //phripheral bit[3:2]:0-RCOSC, 1-crystal, 2-LSI(3K), 3-reserved |1<<0; //cpu bit[1:0]:0-RCOSC, 1-crystal, 2-LSI(3K), 3-reserved //设置时钟分频系数 CMU->CLK_DIV = 0<<10 //RTC bit[14:10]:0-2, 1-2, 2-2, 3-2, 4-4, 5-4, 6-6, 7-6 ...... |0<<5 //phripheral bit[9:5]:0-1, 1-1, 2-2, 3-3, 4-4, 5-5,......31-31 |0<<0; //CPU bit[9:5]:0-1, 1-1, 2-2, 3-3, 4-4, 5-5,......31-31 //外设时钟使能 CMU->PER_EN = 1; //bit[0]:0-off, 1-on //RC频率选择 CMU_RC_DEFAULT->RC_DEFAULT = 0; //bit[0]:0-16MHz, 1-32MHz}

2.外设初始化

2.1外设初始化(串口)

UART_Init_case1(UART1); //串口初始化

由于开发板上使用的晶振为32MHz,那么我们设置0x0116<<8串口波特率就是115200

UARTx->CTRL = 0<<25 //接收中断使能: 0-off,1-on |0<<24 //发送中断使能:0-off,1-on |0x0116<<8 //波特率(对应16M时钟): //0x1a0b-2400,0x0683-9600,0x0341-19200,0x0116-57600,0x008b-115200 //0x0045-230400,0x0023-460800,0x0011-921600,0x000d-1128800 |1<<6 //模式选择:0-模式0,1-模式1,2/3-模式2 |0<<5 //多处理器使能 |1<<4 //接收使能 |0<<3 //发送数据bit8 |0<<2; //接收数据bit8

2.2外设初始化(SPI)

SPI_Init_case1(SPI1); //SPI初始化,非中断模式

CSM32RV20,硬件SPI1引脚说明:PA2-SPI1_SCK,PA3-SPI1_MISO,PA4_SPI1_MOSI.

if(SPIx==SPI1) { //用户自选CSN,软件操作片选信号 //配置SCK GPIO_MODE_Init(GPIOA, PIN2, GPIO_MODE_AF); //PA2复用模式 GPIO_AF_Init(GPIOA, PIN2, GPIO_AF0); //PA2复用到SPI1_SCK //配置MISO GPIO_MODE_Init(GPIOA, PIN3, GPIO_MODE_AF); //PA3复用模式 GPIO_AF_Init(GPIOA, PIN3, GPIO_AF0); //PA3复用到SPI1_MISO //配置MOSI GPIO_MODE_Init(GPIOA, PIN4, GPIO_MODE_AF); //PA4复用模式 GPIO_AF_Init(GPIOA, PIN4, GPIO_AF0); //PA4复用到SPI1_MOSI }

根据Si24R1的SPI协议,CPHA时钟相位和CPOL的时钟极性(SCK空闲时状态为低电平,上升沿采样下降沿输出),选中SPI模式0。SPI速率选择为8分频-4MHz。使用软件CSN控制

SPIx->CTRL = 0x0<<8 //中断使能:0-关闭,1-开启 |0x0<<7 //时钟极性:0-低电平,1-高电平 |0x0<<6 //时钟相位:0-前沿采样,后沿输出,1-前沿输出,后沿采样, |0x1<<4 //SPI使能:0-关闭,1-使能 |0x3; //时钟分频:0-2分频,1-2分频,2-2分频,3-8分频,4-16分频,5-32分频,6-64分频,其他:64分频

2.3外设初始化(GPIO)

初始化CE,CSN,IRQ

2.4外设初始化(中断)

中断IRQ引脚,开发板上选择为PA7。

中断处理函数:

3.Si24R1通信模式介绍

Si24R1通信模式有两种,一种是Si24R1通信模式,一种是兼容模式,两者的区别就在于是否有包控制字,包控制可以实现动态负载长度,ACK通信,ACKPAYLAOD通信等。

Si24R1通信模式:

兼容模式:

4.Si24R1模块

5. SPI函数

SPI读写函数:SPI1读写一个字节

uint8_t spi_rw_byte(uint8_t byte){ uint8_t a; SPI_Transceive(SPI1,&byte,&a,1); return a;}

SPI写寄存器:写数据value到reg寄存器,同时返回寄存器值

uint8_t spi_rw_reg(uint8_t reg,uint8_t value) { uint8_t status; reg |= W_REGISTER ; //写寄存器命令 GPIO_Write(GPIOA,PIN8,GPIO_RESET); status=spi_rw_byte(reg); //选择寄存器,同时返回状态字 spi_rw_byte(value); GPIO_Write(GPIOA,PIN8,GPIO_SET); return status; //返回状态寄存器 }

SPI读寄存器:

//========从reg寄存器中读一个字节的数据========uint8_t spi_rd_reg(uint8_t reg){ uint8_t value; reg |= R_REGISTER ; //读寄存器命令 GPIO_Write(GPIOA,PIN8,GPIO_RESET); spi_rw_byte(reg); value = spi_rw_byte(0); //从该寄存器中读数据 GPIO_Write(GPIOA,PIN8,GPIO_SET); return (value ); //返回状态寄存器}

SPI读BUFF:

SPI写BUFF:

//函数:spi_write_buf()//功能:把pBuf缓存中的数据写入到Si24R1,通常用来写入发射通道数据 或 接收/发送地址//=====================================================================================uint8_t spi_write_buf(uint8_t reg, uint8_t *pBuf, uint8_t bytes){ uint8_t status, i; reg |= W_REGISTER; GPIO_Write(GPIOA,PIN8,GPIO_RESET); // CSN置低,开始传输数据 status = spi_rw_byte(reg); // 选择寄存器,同时返回状态字 for(i = 0; i < bytes; i++) { spi_rw_byte(pBuf[i]); // 逐个字节写入Si24R1 } GPIO_Write(GPIOA,PIN8,GPIO_SET); // CSN拉高,结束数据传输 return(status); // 返回状态寄存器}

6.TX_mode和RX_mode配置

TX_mode: CE拉低后,配置发射地址、发射地址宽度、射频信道、传输速率,发射功率,配置发射模式、CRC、清除STATUS寄存器的标志位!!!(可能在调试程序或者异常退出,没有清除STATUS,但是芯片没断电,可能IRQ的电平一直为低,最好就在初始化时清除STATUS寄存器的标志位。

RX_mode: 发射端的配置与接收端的配置一致即可

//Si24R1 NOACK 接收模式void Si24R1_Rx_Mode(void){ GPIO_Write(GPIOA,CE_Pin,GPIO_RESET); spi_write_buf(RX_ADDR_P0, TX_ADDRESS, 5); // 写入接收地址// spi_rw_reg(FEATURE, 0x01); // 使能 W_TX_PAYLOAD_NOACK 命令 spi_rw_reg(EN_RXADDR , 0x01); // 使能接收通道 spi_rw_reg(RF_CH, 2); // 选择射频通道0x40 spi_rw_reg(RX_PW_P0 ,TX_PLOAD_WIDTH ); // 设置接收通道0负载数据宽度 spi_rw_reg(SETUP_AW, 0x03); // 5 byte Address width spi_rw_reg(RF_SETUP, 0x0f); // 数据传输率 2Mbps spi_rw_reg(CONFIG, 0x0f); //配置为接收方、RC 为 2Bytes spi_rw_reg(STATUS,0xff);//// GPIO_Write(GPIOa,CE_Pin,GPIO_SET);}

Si24R1_TxPacket():发射函数,主要是给TX_FIFO填充数据,CE拉高后就会发射出去。其中要注意:发射前最好擦除FIFO,再填写FIFO,这样对异常的数据发送可以起到一定的屏蔽作用,否则可能会陷入始终发上一包写入数据的怪圈。等到IRQ下降沿中断后,判断是否为发射完成中断,完成即返回TX_OK;

uint8_t Si24R1_TxPacket(){ uint8_t sta; uint8_t TX_BUF[TX_PLOAD_WIDTH] = {0,7,7,5,8,5,2,1}; IRQ_flag=0; spi_rw_reg(FLUSH_TX,0xff); spi_rw_reg(FLUSH_RX,0xff); //GPIO_Write(GPIOA,CE_Pin,GPIO_RESET); //使用NOACK模式时,应使用命令 W_TX_PAYLOAD_NOACK spi_write_buf(W_TX_PAYLOAD_NOACK,TX_BUF,TX_PLOAD_WIDTH);//写数据到TX BUF // spi_write_buf(W_TX_PAYLOAD,TX_BUF,TX_PLOAD_WIDTH);//写数据到TX BUF GPIO_Write(GPIOA,CE_Pin,GPIO_SET);//启动发送 Delay32M_us(10); while(0==IRQ_flag) { NOP; //切记一定得加NOP指令,由于GCC编译器优化问题,程序会只调用一次中断标志。 }//等待发送完成 IRQ_flag=0; sta = spi_rd_reg(STATUS); // 返回状态寄存器 spi_rw_reg(W_REGISTER+STATUS,sta); //清除TX_DS或MAX_RT中断标志 if(sta&MAX_RT)//达到最大重发次数 { spi_rw_reg(FLUSH_TX,0xff);//清除TX FIFO寄存器 return MAX_RT; } if(sta&TX_OK)//发送完成 { return TX_OK; } return 0xff;//其他原因发送失败}

其中,需要注意的是:在等待中断的标志IRQ_flag时,如果直接判断,由于GCC编译器优化,我们利用IDE的反汇编功能,查看下两者的区别:

while(0==IRQ_flag);

while(0==IRQ_flag) { NOP; }

7.通信判断

main()函数中,调用Si24R1_TxPacket();函数,判断返回值是否为发射完成TX_OK标志,闪灯+打印即可。打印这里,虽然库函数里有printf()和ee_printf(),都支持,但是推荐使用ee_printf()函数,这个是简化版的printf函数(而不是C运行库中提供的printf函数),以此生成的代码体积就会更小。

sta=Si24R1_TxPacket( ); Delay32M_ms(500); if(sta==TX_OK) { GPIO_Write(GPIOA,PIN10,GPIO_RESET); Delay32M_ms(500); GPIO_Write(GPIOA,PIN10,GPIO_SET); ee_printf("Hello,IC农民\r\n"); } else Delay32M_ms(20); }

总结

1.注意在等中断IRQ产生后的IRQ_flag时,需要对while(0==IRQ_flag)处理时,在函数里加入一个NOP指令,以此规避GCC编译器优化的问题造成IRQ_flag只判断一次。

2.使用ee_printf()函数,减少代码体积。

3. 在程序里有使能中断时,在使能单个中断后,需要开启中断总开关,否则会出现无法进入中断!!。例如:

Interrupt_Enable(EXIT9_5_int_ID);//CLIC使能EXIT中断 SYS_Interrupt_Enable(); CLIC开总中断

那么,这里,硬件SPI,串口打印,GPIO中断等外设就操作完了。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java中类之间的数据传递方式
下一篇:自动化运维工具-pssh工具安装配置及简单使用讲解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~