基于GCCAVR的模拟SPI程序

简介:

AVR的SPI接口很多只有一个,如果驱动较多的以SPI接口的外设时就必须通过IO来模拟,实际上对于低速外设来说IO模拟的方式也很方便,网上关于模拟SPI的程序很多,我的程序是基于GCCAVR来写的,其他编译器的都类似,写的时候我尽量做到规范和方便后期使用时改动调整。

 

使用时需要注意以下几点:

1、根据外设的时序要求,区分是在上升沿更新数据还是下降沿。

2、发送数据时高位在前还是地位在前。

3、外设对SPI通信有无速度要求,有些时候过快的通信速率可能无法读取和写入数据

4、CLK,数据等引脚的平时电平

上面几点只要对照着外设的时序图一眼就能弄清楚,程序里面写的很清楚相应的改动一下就可以了。

程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/**************************(C) COPYRIGHT emouse 2011***************************
名称:main.c
功能:模拟SPI程序测试
作者:emouse
时间:2011.1.11
版本:1.0
注意:无
*******************************************************************************/
#include"avr/io.h"
#include"avr/interrupt.h"
#include"util/delay.h"
  
#define SetBit(Port,N)  (Port|=(1<<N))    //设置IO某一位
#define ClrBit(Port,N)  (Port&=~(1<<N))   //清空IO某一位
#define ReverBit(Port,N)  (Port^=(1<<N))   //取反IO某一位
#define GetBit(Pin,N)   ((Pin>>N)&0x01)   //读取IO某一位
/***************模拟SPI的相关宏定义********************/
#define SPI1_Port PORTC     //设置使用的端口
#define SPI1_DDR DDRC
#define SPI1_PIN PINC
#define SPI1_CS 0           //设置每个信号对应的引脚
#define SPI1_MISO 1
#define SPI1_MOSI 2
#define SPI1_CLK 3
#define SPI1_CS_H (SPI1_Port|=(1<<SPI1_CS))
#define SPI1_CS_L (SPI1_Port&=~(1<<SPI1_CS))
#define SPI1_GetMISO ((SPI1_PIN>>SPI1_MISO)&0x01)
#define SPI1_MOSI_H (SPI1_Port|=(1<<SPI1_MOSI))
#define SPI1_MOSI_L (SPI1_Port&=~(1<<SPI1_MOSI))
#define SPI1_CLK_H (SPI1_Port|=(1<<SPI1_CLK))
#define SPI1_CLK_L (SPI1_Port&=~(1<<SPI1_CLK))
unsigned  char  spi_delay;     //设置信号的持续时间,相当于设置SPI的速度
/*******************************************************************************
名称:void SPI1_Init()
功能:模拟SPI时序的端口初始化工作
参数:无
时间:2011.1.11
版本:1.0
注意:无
*******************************************************************************/
void  SPI1_Init()
{
     SPI1_Port|=((1<<SPI1_CS)|(1<<SPI1_MISO)|(1<<SPI1_MOSI)|(1<<SPI1_CLK));
     SPI1_DDR|=(((1<<SPI1_CS)|(1<<SPI1_MOSI)|(1<<SPI1_CLK))&(~(1<<SPI1_MISO)));
     SPI1_CS_H;
     SPI1_CLK_L;
     spi_delay=5;
}
/*******************************************************************************
名称:SPI1_Send(unsigned char data)
功能:发送SPI数据
参数:unsigned char data
时间:2011.1.11
版本:1.0
注意:无
*******************************************************************************/
void  SPI1_Send(unsigned  char  data)
{
     unsigned  char  i;
     SPI1_CS_L;       //拉低片选信号
     SPI1_CLK_L;      //时钟空闲时为低电平
     SPI1_MOSI_L;
     _delay_us(spi_delay);
     for (i=0;i<8;i++)
     {
         if (data&(0x80>>i)) //高位在前,低位在前改为(0x01<<i)
             SPI1_MOSI_H;
         else
             SPI1_MOSI_L;
         _delay_us(spi_delay);
         SPI1_CLK_H;      //在上升沿更新数据
         _delay_us(spi_delay);
         SPI1_CLK_L;
     }
     _delay_us(spi_delay);
     SPI1_CS_H;       //拉高片选,完成一次数据传输
}
/*******************************************************************************
名称:unsigned char SPI1_Get()
功能:接收SPI数据
参数:返回data
时间:2011.1.11
版本:1.0
注意:无
*******************************************************************************/
unsigned  char  SPI1_Get()
{
     unsigned  char  i;
     unsigned  char  data=0x00;
     SPI1_CS_L;       //拉低片选信号
     SPI1_CLK_L;      //时钟空闲时为低电平
     SPI1_MOSI_L;
     _delay_us(spi_delay);
     for (i=0;i<8;i++)
     {
         if (SPI1_GetMISO)
             data|=(0x80>>i);
         _delay_us(spi_delay);
         SPI1_CLK_H;      //在上升沿更新数据
         _delay_us(spi_delay);
         SPI1_CLK_L;
     }
     _delay_us(spi_delay);
     SPI1_CS_H;       //拉高片选,完成一次数据传输
     return  data;
}
/*******************************************************************************
名称:void USART0_Init(void)
功能:串口0初始化
参数:无
时间:2011.1.11
版本:1.0
注意:无
*******************************************************************************/
void  USART0_Init( void )
{
UCSR0A=0x20;  //波特率不加倍,单机通信模式
UCSR0B=0x18;  //中断不使能,允许发送和接收
UCSR0C=0x06; //异步模式,无校验,8位数据,1位停止位
UBRR0H=0x00;
UBRR0L=51; //9600波特率   晶振8M
}
/*******************************************************************************
名称:void USART0_Putc(unsigned char c)
功能:发送一个字符
参数:unsigned char c
时间:2011.1.11
版本:1.0
注意:无
*******************************************************************************/
void  USART0_Putc(unsigned  char  c)
{
     while (!(UCSR0A&(1<<UDRE0)));   //等待发送缓冲空
     UDR0=c;     //发送数据
}
/*******************************************************************************
名称:void USART0_Puts(unsigned char * str)
功能:发送字符串
参数:unsigned char * str 待发送的字符串
时间:2011.1.11
版本:1.0
注意:无
*******************************************************************************/
void  USART0_Puts(unsigned  char  * str)
{
     while (*str)
     {
         USART0_Putc(*str++);
     }
}
int  main( void )
{   
     unsigned  char  i=0;
     USART0_Init();   //初始化USART0接口  
     DDRA=0XFF;
     PORTA=0XFF;
     SPI1_Init();
     USART0_Puts( "SPI test" );
     while (1)
     {     
         SPI1_Send(0x04);
         USART0_Putc(SPI1_Get());
         ReverBit(PORTA,0);
         _delay_ms(500);        
     }
}

  本文转自emouse博客园博客,原文链接:http://www.cnblogs.com/emouse/archive/2011/01/11/2198186.html,如需转载请自行联系原作者

相关文章
|
Web App开发 前端开发 JavaScript
Google IO 2022——CSS 状态(上)
Google IO 2022——CSS 状态
128 0
|
SQL 分布式计算 大数据
MaxCompute操作报错合集之在sql 里嵌套查询时,查询条件带有instr时报错,如何解决
MaxCompute是阿里云提供的大规模离线数据处理服务,用于大数据分析、挖掘和报表生成等场景。在使用MaxCompute进行数据处理时,可能会遇到各种操作报错。以下是一些常见的MaxCompute操作报错及其可能的原因与解决措施的合集。
|
Shell Linux
10-20|修改当前时间
10-20|修改当前时间
|
算法 前端开发 JavaScript
前端开发:JS中使用到的贪心算法场景
在前端开发过程中,除了一般的逻辑使用之外,也会涉及到算法相关的知识,比如冒泡排序、数组去重/合并、贪心算法、八皇后算法等等,这些都是比较常用的前端算法相关的知识点。关于前端实际开发中用到的算法,虽然没有后端要求的那么多,但是也有比较重要的算法知识,本篇博文就来分享一下关于贪心算法的相关知识点,记录一下,方便查阅使用。
373 1
前端开发:JS中使用到的贪心算法场景
|
存储 Shell Perl
|
缓存 Oracle 关系型数据库
查看内存使用情况
查看内存使用情况 1.top “2 users”为当前登录到系统的用户,更确切的说是登录到用户的终端数 -- 同一个用户同一时间对系统多个终端的连接将被视为多个用户连接到系统,这里的用户数也将表现为终端的数目; “load average”为当前系统负载的平均值,后面的三个值分别为1分钟前、5分钟前、15分钟前进程的平均数,一般的可以认为这个数值超过 CPU 数目时,CPU 将比较吃力的负载当前系统所包含的进程; 第五行(Swap)表示类别同第四行(Mem),但此处反映着交换分区(Swap)的使用情况。
1060 0
|
7天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!