millwood0 发表于 2011-7-15 09:34:15

Shift1 - sending serial data with only one wire

a typical spi interface requires two wires: SCK to transmit clock, and SDO to transmit data (out).

this can be too much for chips with limited io pins (like pdiop8 or sot5 chips).

so here is an approach proposed by Roman Black that combines SCK / SDO to send serial data.

it essentially uses a r/c network to hold SDO and then quickly strobe out the clock information on the SCK line.

here is how it transmits 0x52 into a hc164:

http://cache.amobbs.com/bbs_upload782111/files_42/ourdev_658024ASLZGE.PNG
(原文件名:send1.PNG)



the transmission is spi compliant in that it sends msb first, and the data is send on sck's rising edge.

millwood0 发表于 2011-7-15 09:36:34

here is the code for 8051 - but can be easily adapted for other mcus.

===========user code======================

#include <regx51.h>                                                //we use keil c51
#include "gpio.h"
#include "delay.h"                                                //we use delay
#include "send1.h"                                                //we use send1 protocol

//hardware configuration
//end hardware configuration

void mcu_init(void) {
}

int main(void) {
        mcu_init();                                                        //reset the mcu
        send1_init();                                                //reset send1
        send1_write(0x52);
        while (1) {
        }
}
==========================


two routines:

1) send1_init(): reset the send1 pins. actually it is empty;
2) send1_write(): send a byte over the send1 bus.

millwood0 发表于 2011-7-15 09:37:03

here is the header file, send1.h:

======================send1.h==================

//send1 header file

//hardware configuration
#define SEND1_PORT                        P2
#define SEND1_DDR                        P2
#define SEND1_SCO                        (1<<0)                //send1 sck/sdo pin
#define SEND1_DLY                        (10)                //time delay to send 1, in us - for 10k/4.7n network
//#define SEND1_DLY                        (20)                //time delay to send 1, in us - for 10k/4.7n network
//define SEND1_DLY                        (10)                //time delay to send 1, in ms - for 10k/47nf network
//end hardware configuration

//initialize send1
void send1_init(void);

//send a byte
void send1_write(unsigned char dat);

millwood0 发表于 2011-7-15 09:37:29

here is the source file


===============send1.c=======================

//using 1 wire to send serial data
//msb first
//on the rising edge

#include <regx51.h>                                                //we use keil c51
#include "gpio.h"
#include "delay.h"                                                //we use delay
#include "send1.h"                                                //we use send1 protocol

//hardware configuration
//end hardware configuration

//initialize send1
void send1_init(void) {
        //IO_SET(SEND1_PORT, SEND1_SCO);                //clear sco
        //IO_OUT(SEND1_DDR, SEND1_SCO);                //sco as output
}

#define send1_delay()                {delay_us(SEND1_DLY);}

//send bit 1
#define send1_1()                        {IO_CLR(SEND1_PORT, SEND1_SCO); IO_SET(SEND1_PORT, SEND1_SCO);}

//send bit 0
#define send1_0()                        {IO_CLR(SEND1_PORT, SEND1_SCO); send1_delay(); IO_SET(SEND1_PORT, SEND1_SCO);}

//send a byte
void send1_write(unsigned char dat) {
        unsigned char mask = 0x80;                        //msb first
       
        do {
                //initialize the bus - bring SCO to high
                IO_SET(SEND1_PORT, SEND1_SCO);                //set sco
                IO_OUT(SEND1_DDR, SEND1_SCO);                //sco as output
                send1_delay();                                //charge up the cap
       
                if (dat & mask) send1_1()                //send 1
                else send1_0();                                        //send 0
                mask = mask >> 1;                                //shift to the next bit
        } while (mask);
}

millwood0 发表于 2011-7-15 09:39:12

depending on user requirements, you can adjust the value of the r/c network, and then SEND1_DLY and send1_delay() accordingly.

longer SEND1_DLY or longer r/c constant gives better reliability, but slows down the speed.

typical speed? with the value given, it takes 1.5ms to send a byte, vs. 0.1ms typically using two pins.

huayuliang 发表于 2011-7-15 09:41:21

这样弄...一旦修改频率,RC的值就得改.
某些场合还是值得的。

millwood0 发表于 2011-7-15 22:09:12

"一旦修改频率,RC的值就得改. "

no, if your send1_delay() routine gives the same delay duration under different cpu speed.

huayuliang 发表于 2011-7-16 12:06:31

回复【6楼】millwood0
-----------------------------------------------------------------------

哈哈。。。还有软件呢。。俺光想着硬件了。
如果是特定的硬件时序需求,R、C固定下来后,send1_delay也是可以根据CPU频率计算出来的。

汗。。俺回的贴应该是在1楼啊。。当时没提交?

mzbhy 发表于 2011-7-16 12:12:04

嗯学习学习。

millwood0 发表于 2011-7-19 08:42:59

"如果是特定的硬件时序需求,R、C固定下来后,send1_delay也是可以根据CPU频率计算出来的。 "

that's correct. all you need is for send1_delay() to be sufficiently long so that the voltage on the capacitor has been below the lowest input high.

Vih>Vcc*e(-t/(rc)).
页: [1]
查看完整版本: Shift1 - sending serial data with only one wire