打印

软件模拟SPI口的一些思考

[复制链接]
3166|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sinanjj|  楼主 | 2007-11-29 16:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
如果我们要把240bit的数据通过模拟SPI口传送出去, 一般的我们定义一数组, 把240bit的数据放在30个byte里, 然后, 通过

tempi=nodeConfig[ByteCnt];
 for(BitCnt=0;BitCnt!=8;BitCnt++)
  {
  PORTA&=0xFD; //1111 1101, CLK=0
  if(tempi&0x80) //1000 0000
  PORTA|=0x04; //0000 0100, data(configuration word) output=1; PA2
  else
  PORTA&=0xFB; //1111 1011, data(configuration word) output=0; PA2
  delay_1us();
  PORTA|=0x02; //0000 0010, CLK=1
  delay_1us();
  PORTA&=0xFD; //CLK=0
  tempi=tempi<<1;
  }

之类的代码传输给外设. 

但是, 我们的编程中需要对这240个bit频繁的操作, 最好定义成结构体, 但是, 结构体就不能用上面的方法模拟SPI口了, 因为结构体中有1byte的有1bit的有2byte的, 所以....


不知各位对此有何高见

谢谢指点先.

相关帖子

沙发
computer00| | 2007-11-29 17:07 | 只看该作者

强制类型转换为数组来发不行吗?

使用特权

评论回复
板凳
xwj| | 2007-11-29 17:18 | 只看该作者

用联合或强制转换成指针操作啦

使用特权

评论回复
地板
computer00| | 2007-11-29 17:26 | 只看该作者

按字节发送,对方按字节接收就行了

Struct TCB
{
int deadline;
unsighed state:1; //位域在结构体中
unsighed rt:1; //位域在结构体中
int sp;
struct TCB *prev,next; //结构体指针以构成链表
struct TASK *p_task; //结构体指针指向其他结构体
proc_t *do_error;
}TCB[n_tasks];//声明了一个Struct TCB结构的结构体数组




for(i=0;i<sizeof(TCB[0]);i++)
{
 send(((unsigned char *)(&(TCB[0]))));
}

使用特权

评论回复
5
xwj| | 2007-11-29 17:34 | 只看该作者

是的,就如小蛋蛋所说.

使用特权

评论回复
6
sinanjj|  楼主 | 2007-11-29 21:18 | 只看该作者

整理了一下相关资料

变量类型转换: 1, 不同类型的变量运算时自动转换. 2, 强制类型转换
(类型说明符)(表达式); //把表达式的运算结果强制转换成类型说明符所表示的类型.
(float)a; //把a转换为实型
(int)(x+y); //类型说明符和表达式都必须加括号(单个变量可以不加括号).
(无论是强制转换或是自动转换, 都只是为了本次运算的需要而对变量的数据长度进行的临时性转换, 不改变数据说明时对该变量定义的类型)
3, 指针类型强制转换: 指针p: 
(TYPE*)p;
这样强制类型转换的结果是一个新指针, 该新指针的类型是TYPE*, 它指向的类型是TYPE, 它指向的地址就是原指针指向的地址.
4, 强制转换成指针类型: unsigned int a; TYPE *ptr; a=0x0001; ptr=(TYPE*)a; //把a强制转换成指向TYPE类型的指针. 转换过程中a的值不变, 即(TYPE*)a表示0x0001地址开头的TYPE结构的结构体变量. 所以, ptr指向的地址为0x0001. 这是一种实现对地址直接操作的方法, 但是注意0x0001开始处必须有TYPE结构的变量, 不然会产生内存越界而导致错误. 
5, 指针强制类型转换: 用新的指针类型来解析原来地址空间中的内容   

struct aaa
{
char id;char cmd;char byte[4];
}aaa1;
struct bbb
{
char id;char cmd;char *ptr;
}bbb1;
运行到了程序某处, 执行了指针强制类型转换: bbb1=(struct bbb*)aaa1;
假定aaa1强制类型转换前的空间的内容是
(struct aaa)
1byte    1byte     4bytes
id       cmd       byte[4]
0x01     0x02      0x03040506
强制类型转换之后, 就要以struct bbb来解析该内容
bbb1, 一共6bytes
1byte    1byte      4bytes
id       cmd        ptr
0x01     0x02      0x03040506
原来byte[4]的内容成为ptr的内容, 而不是byte[4]的首地址. 即: ptr指向的地址为0x03040506, bbb1->ptr为地址0x03040506处存放的值.

使用特权

评论回复
7
sinanjj|  楼主 | 2007-11-29 21:24 | 只看该作者

00所说, 本人还不能完全理解, 我要花些时间研究(佩服00)


for(i=0;i<sizeof(TCB[0]);i++)
{
send(((unsigned char *)(&(TCB[0]))));
}

使用特权

评论回复
8
qqqq4com| | 2007-11-29 21:29 | 只看该作者

中国商务导航网

这里有大量的电子信息 中国商务导航网
相关链接:http://www.qqqq4.com/

使用特权

评论回复
9
sinanjj|  楼主 | 2007-11-29 21:33 | 只看该作者

理论上很好理解, 我要用编译器验证一下(感觉很玄啊)

((unsigned char *)(&(TCB[0])))
 ---数组, 前边括号里的一定是数组指针
(&(TCB[0]))---TCB的地址(TCB[]--直接能转成数组么??)
(unsigned char *) --把TCB的地址变成一个指向char的地址.

把结构体强制成数组了. 

我试试

使用特权

评论回复
10
computer00| | 2007-11-29 21:48 | 只看该作者

呵呵,对方接收时也使用同样的结构体

按照同样的顺序放进去,那么结果就刚好对上了。

使用特权

评论回复
11
sinanjj|  楼主 | 2007-11-29 22:59 | 只看该作者

不知什么原因, 不能编译通过.测试代码如下(ICC编译)

//ICC-AVR application builder : 2007-11-29 22:23:09
// Target : M16
// Crystal: 8.0000Mhz

#include <iom16v.h>
#include <macros.h>

void port_init(void)
{
 PORTA = 0x00;
 DDRA  = 0x00;
 PORTB = 0x00;
 DDRB  = 0x00;
 PORTC = 0x00; //m103 output only
 DDRC  = 0x00;
 PORTD = 0x00;
 DDRD  = 0x00;
}

//call this routine to initialize all peripherals
void init_devices(void)
{
 //stop errant interrupts until set up
 CLI(); //disable all interrupts
 port_init();

 MCUCR = 0x00;
 GICR  = 0x00;
 TIMSK = 0x00; //timer interrupt sources
 SEI(); //re-enable interrupts
 //all peripherals are now initialized
}

main()
{
unsigned char aa[34];
unsigned char i;
struct TCB
 {
 int deadline;
 unsigned state:1; //位域在结构体中
 unsigned rt:1; //位域在结构体中
 int sp;
 struct TCB *next; //结构体指针以构成链表
 }TCB[5];//声明了一个Struct TCB结构的结构体数组
//把结构体TCB[0]强制转换成unsigned char数组:
for(i=0;i<sizeof(TCB[0]);i++) //sizeof(): 求数据类型所占的byte数, sizeof(TCB[0])代表TCB[0]占的byte数.
 { 
 aa=(unsigned char*)(&(TCB[0])));
 } //send(unsigned char temp): 发送temp到目的地. (&(TCB[0]))代表结构体TCB[0]的起始地址, (unsigned char *)把TCB[0]的起始地址强制转换成一个指向unsigned char类型的指针. 存在, 一般的数组为aa, aa表示数组的起始地址, 而((unsigned char *)(&(TCB[0])))正好是一个指向unsigned char类型的指针, 符合数组形式. 
}

使用特权

评论回复
12
computer00| | 2007-11-29 23:14 | 只看该作者

晕...照着抄下来也错?少了一个(......

使用特权

评论回复
13
赤铸| | 2007-11-30 00:27 | 只看该作者

人嘛,需要高级思想,也需要低级趣味

LZ 之所以觉得难以理解就是该低级的时候低不下来

数据的“意义”是人为赋予的,你认为这个是TCB.state,那个是什么指针,
但在数据通信的层次,那就全是比特、字节……

通信的基本思想就是“分层”,在传输这一层,就应该不管内容,只管按字节拷贝,拷贝过去原样恢复就是了

使用特权

评论回复
14
567| | 2007-11-30 12:09 | 只看该作者

要效率还是通用性

要效率,就使用联合、指针、类型转换等。

要通用性、可移植性,就用 与 或 等操作拷贝到另一个数组中再处理。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

456

主题

6300

帖子

25

粉丝