文章目录
概述
本项目硬件平台采用君正x1600平台,使用pan3028(调制解调技术的低功耗远距离无线收发芯片)做无线传输。
硬件连接
比较简单,不再详细说明
这里说下主要涉及的引脚接口,连接方式不限于此
pan3028 <> soc(jz-x1600)
spi接口 <> spi0
irq引脚 <==> pb15
分析
官方的pan3028测试程序是基于STM32 HAL库的,因此需要准备
1、SOC:spi、gpio hal层接口
2、SOC:spi platform驱动和spi设备驱动
另外要考虑pan3028使用的引脚,是否被其他驱动模块使用,例如君正i2c驱动默认使用了pb15引脚作为clk
移植
准备工作
1、安装驱动
# lsmod
Module Size Used by Tainted: G
spidev 5936 0
spidev_helper 1958 0
soc_gpio 5086 0
soc_spi 12984 0
utils 13815 3 spidev_helper,soc_gpio,soc_spi
2、在官网下载pan3028 demo
移植
pan3028 demo使用的平台接口是stm32 hal库接口,移植工作主要是移植平台接口,主要包括如下内容
初始化gpio
pan3028发送或接收完毕后,均会触发irq引脚拉高,故需要对irq引脚初始化,并判断其电平
拷贝君正libhardware/gpio.c到demo中,并修改demo-init接口初始化gpio方式
char *func[] = {"func1"};
g_gpio_fd = gpio_open();
if (g_gpio_fd < 0)
return FAIL;
gpio_set_func(g_gpio_fd, IRQ_GPIO, func, 1);
初始化spi
x1600 spi0传输频率最高10M,pan3028设置为200k或400k即可。
注意,spi传输模式必须和pan3028数据手册上的时序图一致,为SPI_MODE_0,否则会spi会读写失败
int platform_spi_init(char *cs_pin)
{
int spi_fd = 0;
/* 1.spi初始化 */
register_data.cs_gpio = cs_pin;
register_data.busnum = 0;
// 1.1.注册spi设备
if(spi_add_device(®ister_data) < 0) {
printf("spi register fail\n");
return -1;
}
// 延时等待设备节点生成
usleep(1000*1000);
// 1.2.打开spi设备
spi_fd = spi_open(register_data.spidev_path);
if (spi_fd < 0) {
printf("spi open fail,spi_fd=%d\n",spi_fd);
return -1;
}
// 1.3.设置spi传输模式
if (spi_set_mode(spi_fd, SPI_MODE_0) < 0) {
printf("spi set mode fail \n");
return -1;
}
// 1.4.设置spi传输速率
if (spi_set_speed(spi_fd, 400*1000) < 0) {
printf("spi set speed fail\n");
return -1;
}
// 1.5.设置spi传输的数据位数
if (spi_set_bits(spi_fd, 8) < 0) {
printf("spi set bits fail\n");
return -1;
}
// 1.6.设置spi传输数据高低位发送顺序
if (spi_set_lsb(spi_fd, 0) < 0) {
printf("spi set lsb fail \n");
return -1;
}
printf("spi init ok\n");
return spi_fd;
}
pan3028初始化
pan3028初始化主要通过soc的spi接口,下发配置寄存器值,需注意:
linux内核spi收发接口,每读写一次,内部cs会先拉选中,后恢复
具体过程如下:
jz_spi_transfer_one_message
//如果spi模式和初始模式不一致,则重新配置
jz_spi_config
//使能CS
if (cs_change)
enable_cs(hw, spi);
//发送数据
jz_spi_transfer
//关闭CS
if (cs_change && !list_is_last(&xfer->transfer_list, &msg->transfers))
disable_cs(hw, spi);
而pan3028要求,读写设备寄存器按如下格式:
读寄存器:
addr_r + 0x00
写寄存器:
addr_w + u8_data
其中地址,高7位为地址,第一位为读写位,0=读,1=写
因此,读写寄存器需一次发送两个字节(地址字节+数据字节),中间CS不能被disable,否则读写失败。
rx、tx测试
整体采用demo的代码即可,但需注意如下几点:
第一个usleep:不加读取irq寄存器为空
第二个usleep:如果休眠时间较长,无法触发rx irq,获取rx数据
while(1)
{
if(g_run_mode == em_TX_MODE || g_run_mode == em_TXRX_MODE) {
printf("start to send tx data\n");
if(!rf_single_tx_data(send_buff, sizeof(send_buff), &tx_time)) {
printf("wait send finish...\n");
while(pan3028_radio_process()){ // 等待发送完成
usleep(200*1000); //必须等待,否则设备IRQ寄存器值会被刷掉
}
}
printf("send finish !\n");
}
if(g_run_mode == em_RX_MODE || g_run_mode == em_TXRX_MODE) {
/* 接收处理 */
printf("start to recv rx data\n");
pan3028_radio_process();
}
usleep(200*1000);
}