您的位置:首页 > 编程语言

beaglebone black spi使用笔记(2)-adt7320代码编写

2015-06-12 16:07 417 查看
这里使用adt7320芯片来测试SPI1接口.

linux的spi驱动为用户提供了很多命令: 配置总线时序, 配置总线速率等

1 设置极性和相位(spi四种模式)



2 读取极性和相位



3 设置每 字 的长度



4 设置最大总线速率



5 数据接收/发送命令



struct spi_ioc_transfer {
__u64 tx_buf;      //指向要发送数据的缓冲区
__u64 rx_buf;      //指向要接收数据的缓冲区
__u32 len;           // 发送数据和接收数据缓冲区中数据的长度
__u32 speed_hz; // 发送/接收这些数据需要的总线速率
__u16 delay_usecs;
__u8 bits_per_word; // 发送/接收这些数据在 SPI 总线上,每字是多少位
__u8 cs_change;
__u32 pad;
}
len 是指 tx_buf和 rx_buf所指向的缓冲区长度,而 speed_hz 不能大于SPI_IOC_WR_MAX_SPEED_HZ 命令设置的的总线速率。

当只需要发送数据时,需要将 rx_buf指向的缓冲区全填充‘ \0’,然后将要发送的数据填充到 tx_buf指向的缓冲区;

当只需要接收数据时,需要将 tx_buf指向的缓冲区全填充‘ \0’,而接收到的数据会保存在 rx_buf指向的缓冲区;

当在发送数据的同时需要接收数据,那么当 tx_buf指向的缓冲区中的数据发出后,同时接收的数据将返回在 rx_buf指向的缓冲区中。

直接上代码:

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#define Contin_Mode 	0x00
#define OneShot_Mode	0x01
#define SPS1_Mode 		0x02
#define ShutDown_Mode 	0x03

#define Bit16_Mode  1
#define Bit13_Mode  0

#define Read  1
#define Write 0

#define Status_Reg 	0x00
#define Config_Reg 	0x01
#define TempVal_Reg 0x02
#define ID_Reg 		0x03
#define TCRIT_Reg 	0x04
#define THYST_Reg 	0x05
#define THIGH_Reg 	0x06
#define TLOW_Reg 	0x07

#define Dummy_Byte  0x5A

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

static void pabort(const char *s)
{
perror(s);
abort();
}

static const char *device = "/dev/spidev1.0";
static uint8_t bits = 8;
static uint32_t speed = 50000;
static uint16_t delay = 0;

static void Reset(int fd)
{
int ret;
uint8_t tx[] = {
0xFF, 0xFF, 0xFF, 0xFF
};
uint8_t rx[ARRAY_SIZE(tx)] = {0, };
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");
/*
for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
printf("%.2X ", rx[ret]);
}
*/
puts("Reset Done\n");
}

/*******************************************************************************
* Function Name  : Reg_Select
* Description    : 选中 adt7320 的寄存器, 指定操作读或写
* Input          : operate:  0 读 / 1 写, val 寄存器编号
width: 设置数据宽度, 13bit or 16bit.
* Return         : None
*******************************************************************************/
uint8_t Reg_Select(unsigned char operate, unsigned char val)
{
uint8_t cmd = 0;

if (operate)//bit7: 1 读 , 0 写
{
cmd |= (1 << 6);
}
else
{
cmd &= ~(1 << 6);
}

cmd |= (val << 3);
cmd &= ~((1<<7) | (1<<2) | (1<<1) | (1<<0));

return cmd;
}
/*******************************************************************************
* Function Name  : GetId
* Description    : 读取芯片的ID寄存器,检测芯片是否正常
* Input          : 文件描述符
* Return         : 芯片的id值
*******************************************************************************/
uint8_t Get_Id(int fd)
{
uint8_t chip_id;
uint8_t cmd;
int ret;

cmd = Reg_Select(Read, ID_Reg);				//读取ID寄存器

uint8_t tx[] = {
cmd, 0xFF
};
/*
for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
printf("%#x ", tx[ret]);
}
*/
uint8_t rx[ARRAY_SIZE(tx)] = {0, };
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");

chip_id = rx[1];
/*
for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
printf("%#x ", rx[ret]);
}
*/
//puts("Get ID Done\n");

return chip_id;
}

/*******************************************************************************
* Function Name  : Get_temp
* Description    : 获取温度值
* Input          : 文件描述符
* Return         : 温度值
*******************************************************************************/
float Get_temp(int fd)
{
int ret;
short Adc_val;
float temp_val;

uint8_t cmd = Reg_Select(Read, TempVal_Reg);

uint8_t tx[] = {
cmd, 0xFF, 0xFF
};
uint8_t rx[ARRAY_SIZE(tx)] = {0, };
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");
/*
for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
printf("%.2X ", rx[ret]);
}
*/

Adc_val = (rx[1] << 8) + rx[2];
temp_val = (float)(Adc_val >> 3);	//低3位为标志位
if (Adc_val & 0x8000)				//最高位为1则为负值
{
temp_val = (temp_val - 8192) / 16.0;
}
else
{
temp_val = temp_val / 16.0;
}
//puts("Get Temp Done");
return temp_val;
}

/*******************************************************************************
* Function Name  : Init
* Description    : 获取温度值
* Input          : 文件描述符
* Return         : 测量的温度值
*******************************************************************************/
static void Init(int fd)
{
int ret;
uint8_t config;
uint8_t cmd;

config = (Contin_Mode<<5) | (Bit13_Mode<<7);//配置为循环模式, 13bit
cmd = Reg_Select(Write, Config_Reg);
uint8_t tx[] = {
cmd, config
};
uint8_t rx[ARRAY_SIZE(tx)] = {0, };
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");
/*
for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
printf("%.2X ", rx[ret]);
}
*/
//puts("Init Done\n");
}

int main(int argc, char const *argv[])
{
int fd = 0, ret = 0;
uint8_t cnt = 0;
uint8_t chip_id;
uint8_t mode = SPI_MODE_3;

fd = open(device, O_RDWR);
if (fd < 0)
{
pabort("can not open device");
}

/*
* spi mode
*/
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1) {
pabort("can't set wr spi mode");
}
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1) {
pabort("can't get spi mode");
}
/*
* bits per word
*/
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1) {
pabort("can't set bits per word");
}
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1) {
pabort("can't get bits per word");
}
/*
* max speed hz
*/
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1) {
pabort("can't set max speed hz");
}
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1) {
pabort("can't get max speed hz");
}
printf ("spi mode: %d\n", mode);
printf ("bits per word: %d\n", bits);
printf ("max speed: %d Hz (%d KHz)\n", speed, speed/1000);

Reset(fd);
chip_id = Get_Id(fd);
if (chip_id != 0xC3)
{
printf ("chip error !");
close(fd);

return -1;
}
else
{
printf ("chip ID: %#x\n", chip_id);
}

Init(fd);
sleep (1);

while (cnt < 15)
{
printf ("temp = %f\n", Get_temp(fd));
cnt++;
sleep (1);
}

close(fd);

return 0;
}
在读取温度的时候

第一byte: bbb发给adt7320的命令 cmd

第二byte:adt7320返回给bbb

第三byte:adt7320返回给bbb

tx[3] = {cmd, xxx, xxx} ; 其中xxx随意, 只是为了让bbb继续发送时钟. 这样写入cmd之后再发送两个byte的时钟, bbb就已经拿到adt7320返回的数据了结果保存在

rx[3]中, 其中 rx[1] rx[2]就是adt7320返回的数据
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: