WIZwiki-W7500学习(2)使用SPI读取DS18B20
距离第一次测试,已经很久了,这次带来的是使用SPI读取DS18B20的温度我们知道ds18b20需要很严格的时序,一般用纯软件的做法,当然效果不是很好,也有用串口的。我支持利用SPI,好处是,读取时不需要关中断。7500带有两个SPI口,支持DMA,FIFO。
因为这个芯片的DMA我不是很熟悉,所以就用了FIFO,为了保证连续发送,所以这个实现需要一个250us秒的定时器,当然,如果你循环周期永远不会大于380,那么在主循环中调用就可以。
直接上代码吧,写起来发现很费劲。
#include "spidrv.h"
#include "W7500x.h"
/* < SSP_StructInit default values
SSP_InitStructure.SSP_SerialClockRate = 0x00;
SSP_InitStructure.SSP_FrameFormat = SSP_FrameFormat_MO;
SSP_InitStructure.SSP_CPHA = SSP_CPHA_1Edge;
SSP_InitStructure.SSP_CPOL = SSP_CPOL_Low;
SSP_InitStructure.SSP_DataSize = SSP_DataSize_8b;
SSP_InitStructure.SSP_SOD = SSP_SOD_RESET;
SSP_InitStructure.SSP_Mode = SSP_Mode_Master;
SSP_InitStructure.SSP_NSS = SSP_NSS_Hard;
SSP_InitStructure.SSP_LBM = SSP_LBM_RESET;
SSP_InitStructure.SSP_SSE = SSP_SSE_SET;
SSP_InitStructure.SSP_BaudRatePrescaler = SSP_BaudRatePrescaler_2;
*/
static u32t _fsm = 0;
static struct timer _timer;
static SSP_InitTypeDef SSP1_InitStructure;
void spi_init(void) {
_fsm = 0;
/* SSP0 Init -- SSP Master */
//SSP_StructInit(&SSP0_InitStructure);
//SSP0_InitStructure.SSP_FrameFormat= SSP_FrameFormat_MO; // Motorora SPI mode
//SSP0_InitStructure.SSP_DataSize = SSP_DataSize_16b;
//SSP_Init(SSP0,&SSP0_InitStructure);
/* SSP1 Init -- SSP Slave */
SSP_StructInit(&SSP1_InitStructure);
SSP1_InitStructure.SSP_DataSize = SSP_DataSize_16b;
SSP1_InitStructure.SSP_BaudRatePrescaler = SSP_BaudRatePrescaler_254;// SSP_BaudRatePrescaler_254;
SSP1_InitStructure.SSP_Mode = SSP_Mode_Master;
SSP1_InitStructure.SSP_CPOL = SSP_CPOL_Low;//SSP_CPOL_High;
SSP1_InitStructure.SSP_FrameFormat = SSP_FrameFormat_MO;
SSP1_InitStructure.SSP_CPHA = SSP_CPHA_2Edge;
SSP_Init(SSP0,&SSP1_InitStructure);
//SSP0->DMACR= 0x03;
//bsp_set_spi1_speed(SPI_SPEED_256);
//*(u32t *)(0x41003020) = 0x32;
*(u32t *)(0x4100301c) = 0x32;
}
#define ff10xffff
#define ff2ff1, ff1
#define ff3ff1, ff2
#define ff4ff1, ff3
#define ff5ff1, ff4
#define ff6ff1, ff5
#define ff7ff1, ff6
#define ff8ff1, ff7
#define ff9ff1, ff8
#define ff10ff1, ff9
#define zz10x0
#define zz2zz1, zz1
#define zz3zz1, zz2
#define zz4zz1, zz3
#define zz5zz1, zz4
#define zz6zz1, zz5
#define zz7zz1, zz6
#define zz8zz1, zz7
#define zz9zz1, zz8
#define zz10zz1, zz9
#define zz11zz1, zz10
//3.5us
//16 ->56
//rst 500us-> 9个0x0000;
//rst wait 15-60us ->2个0xffff
//rst read 0xffffread value
// 9个0xffff;
//, 0xffff
//, 0xffff
#define WRITE10x7fff, 0xffff
#define WRITE00x0000, 0xffff
//write 1
//0x1fff, 0xffff
//write 0
//0x0000, 0x0fff
//, 0xffff, 0xffff
#define RD1 0x7fff, 0xffff
#define RD2 RD1, RD1
#define RD3 RD1, RD2
#define RD4 RD1, RD3
#define RD5 RD1, RD4
#define RD6 RD1, RD5
#define RD7 RD1, RD6
#define RD8 RD1, RD7
//read 0x7fff, 0xffff
//0x2000 & ,如果== 0,
//16
//CC
#define SKIPADDR WRITE0, WRITE0, WRITE1, WRITE1, WRITE0, WRITE0, WRITE1, WRITE1
//44
#define CONVERTWRITE0, WRITE0, WRITE1, WRITE0, WRITE0, WRITE0, WRITE1, WRITE0
//BE 1011 1110
#define RCMD WRITE0, WRITE1, WRITE1, WRITE1, WRITE1, WRITE1, WRITE0, WRITE1
/*
#define SKIPADDR WRITE1, WRITE1, WRITE0, WRITE0, WRITE1, WRITE1, WRITE0, WRITE0
//44
#define CONVERTWRITE0, WRITE1, WRITE0, WRITE0, WRITE0, WRITE1, WRITE0, WRITE0
//BE 1011 1110
#define RCMD WRITE1, WRITE0, WRITE1, WRITE1, WRITE1, WRITE1, WRITE1, WRITE0
*/
#define BUFLENGTH (36 + 88 + 5 + 88)
#define DSDATA1_LENGTH (27 + 16 * 2)
#define DSDATA2_LENGTH (27 + 16 * 2 + 16 * 9)
const u16t dsdata1 = { ff7, zz11, ff9, SKIPADDR, CONVERT};
const u16t dsdata2 = { ff7, zz11, ff9, SKIPADDR, RCMD, RD8, RD8, RD8, RD8,RD8,RD8, RD8,RD8,RD8};
#define MAXBUFLENGTH(DSDATA1_LENGTH + DSDATA2_LENGTH + DSDATA3_LENGTH + DSDATA4_LENGTH)
#define DATA_OFFSET (DSDATA1_LENGTH + DSDATA2_LENGTH)
static u8t _rbuf;
static s32t index, rindex;
//CRC = X8 + X5 + X4 + 1
const u8t Crc8Table ={
0,94, 188,226,97,63,221,131,194,156,126,32,163,253,31,65,
157,195,33,127,252,162,64,30,95,1,227,189,62,96,130,220,
35,125,159,193,66,28,254,160,225,191,93,3,128,222,60,98,
190,224,2,92,223,129,99,61,124,34,192,158,29,67,161,255,
70,24,250,164,39,121,155,197,132,218,56,102,229,187,89,7,
219,133, 103,57,186,228,6,88,25,71,165,251,120,38,196,154,
101,59, 217,135,4,90,184,230,167,249,27,69,198,152,122,36,
248,166, 68,26,153,199,37,123,58,100,134,216,91,5,231,185,
140,210, 48,110,237,179,81,15,78,16,242,172,47,113,147,205,
17,79,173,243,112,46,204,146,211,141,111,49,178,236,14,80,
175,241, 19,77,206,144,114,44,109,51,209,143,12,82,176,238,
50,108,142,208,83,13,239,177,240,174,76,18,145,207,45,115,
202,148, 118,40,171,245,23,73,8,86,180,234,105,55,213, 139,
87,9,235,181,54,104,138,212,149,203,41,119,244,170,72,22,
233,183,85,11,136,214,52,106,43,117,151,201,74,20,246,168,
116,42,200,150,21,75,169,247,182,232,10,84,215,137,107,53};
u8t GetCRC(u8t *str, u32t length) {
u8t crc_data=0;
u32t i;
for(i=0;i<length;i++) {//查表校验
crc_data = Crc8Table];
}
return (crc_data);
}
void spi_recive(void) {
s32t t, r, i;
while(SSP_GetFlagStatus(SSP0, SSP_FLAG_RNE) == SET) {
t = (u16t)SSP_ReceiveData(SSP0);
if ((rindex >= 0) && ((rindex & 0x01) == 0)) {
t &= 0x0f00;
i = rindex / 16;
r = _rbuf;
r >>= 1;
r &= 0x7f;
if (t == 0x0f00) {
r |= 0x80;
}
_rbuf = r;
}
rindex++;
}
}
s32t wd;
void spi_process(void) {
u8t temp;
u8t TL,TH;
s32t tem;
TL = _rbuf; // LSB
TH = _rbuf; // MSB
if(TH>7) {
TH=~TH;
TL=~TL;
temp=0;//温度为负
}
else {
temp=1;//温度为正
}
tem=TH<<8 | TL; //获得不带符号位的11位温度值
//转换 *0.625
tem = tem*10000;
tem = tem>>4;
if(temp) {
wd = tem;
}
else{
wd = -tem;
}
}
s32t spi_temperature(void){
return wd;
}
#define FSM_INIT 0
#define FSM_READY 1
#define FSM_WAITFREE 2
#define FSM_SEND_DATA1 3
#define FSM_WAIT_DATA1_OK 4
#define FSM_SEND_DATA2 5
#define FSM_WAIT_DATA2_OK 6
#define FSM_WAIT_CONVERT 7
void spi_timerpoll(void) {
if (_fsm == FSM_SEND_DATA1) {
while((SSP_GetFlagStatus(SSP0, SSP_FLAG_TNF) == SET) && index < DSDATA1_LENGTH) {
SSP_SendData(SSP0, dsdata1);
}
if(index >= (DSDATA1_LENGTH)) {
timer_init(&_timer);
_fsm = FSM_WAIT_DATA1_OK;
}
}
else if (_fsm == FSM_SEND_DATA2) {
spi_recive();
while((SSP_GetFlagStatus(SSP0, SSP_FLAG_TNF) == SET) && index < DSDATA2_LENGTH) {
SSP_SendData(SSP0, dsdata2);
}
spi_recive();
if(index >= DSDATA2_LENGTH) {
_fsm = FSM_WAIT_DATA2_OK;
}
}
}
void spi_service(void) {
u32t temp_interrupt;
temp_interrupt = (NVIC->ISPR);
(NVIC->ISPR) = (u32t)0xFFFFFFFF;
if ((_fsm == FSM_SEND_DATA1) || (_fsm == FSM_SEND_DATA2)) {
(NVIC->ISPR) = temp_interrupt;
return;
}
(NVIC->ISPR) = temp_interrupt;
//CTX_EXIT();
if (_fsm == FSM_READY) {
if (timer_expired(&_timer, 9000)) {
while(SSP_GetFlagStatus(SSP0, SSP_FLAG_RNE) == SET) {
SSP_ReceiveData(SSP0);
}
printf("\r\nGetting Started\r\n");
index = 0;
_fsm = FSM_SEND_DATA1;
}
}
else if(_fsm == FSM_WAIT_DATA1_OK) {
if (timer_expired(&_timer, 1000)) {
while(SSP_GetFlagStatus(SSP0, SSP_FLAG_RNE) == SET) {
SSP_ReceiveData(SSP0);
}
index = 0;
rindex = 16 * 9 - DSDATA2_LENGTH;
_fsm = FSM_SEND_DATA2;
}
}
else if(_fsm == FSM_WAIT_DATA2_OK) {
spi_recive();
if (SSP_GetFlagStatus(SSP0, SSP_FLAG_BSY)) {
return;
}
spi_recive();
/*
t = _rbuf;
t <<= 4;
printf("SET __%d__%d\r\n", index, rindex);
rindex /= 16;
for(i = 0; i < rindex; i++){
printf("%04X ", _rbuf);
}
printf("\r\nSET END \r\n");*/
if (GetCRC(_rbuf, 8) == _rbuf) {
spi_process();
printf("Measuring success:%03d.%04d\r\n", wd / 10000, wd %10000);
//printf("\r\nwd crc ok {%08d} \r\n", wd);
}
else {
printf("Measurement fails\r\n");
}
_fsm = FSM_INIT;
}
else {
timer_init(&_timer);
_fsm = FSM_READY;
}
}
其中spi_timerpoll必须保证在380us内调用一次(我测试时放在一个250us的定时器里调用),spi_service放在主循环中调用 W7500可以买到了? liudan 发表于 2015-8-20 10:45
W7500可以买到了?
上次问了下,说可能比stm32f107便宜一点点 liudan 发表于 2015-8-20 10:45
W7500可以买到了?
我这个是在评估板上进行的测试
页:
[1]