ATtiny88初体验(六):SPI
ATtiny88初体验(六):SPI
SPI介绍
ATtiny88自带SPI模块,可以实现数据的全双工三线同步传输。它支持主从两种模式,可以配置为LSB或者MSB优先传输,有7种可编程速率,支持从空闲模式唤醒。

注意:为了使用SPI模块,必须将 PRR 寄存器中的 PRSPI 位设置为0。
ATtiny88的SPI时钟频率不能超过 \(f_{OSC}/4\) ,双倍速率模式下不能超过 \(f_{OSC}/2\) 。
当SPI使能时,MOSI、MISO、SCK、SS引脚的方向会被覆盖,具体见下表:

根据SCK的极性和相位不同,SPI分为四种模式:



寄存器

SPIE:写入1使能SPI中断。SPE:写入1使能SPI。DORD:数据方向,写入1为LSB优先,写入0为MSB优先。MSTR:主机/从机模式选择,写入1为主机模式,写入0为从机模式。CPOL:时钟极性。CPHA:时钟相位。SPR[1:0]:SPI时钟速率选择。


SPIF:SPI中断标志,执行完中断后自动清除,或者通过先读SPSR寄存器,再访问SPDR寄存器清除。WCOL:写冲突标志,在数据传输期间对SPDR寄存器进行写操作时置位,通过先读SPSR寄存器,再访问SPDR寄存器清除。SPI2X:SPI速率加倍。在主机模式下,向此位写入1使SPI时钟速率加倍,最大速率为 \(f_{OSC}/2\) 。在从机模式下,最大速率还是只有 \(f_{OSC}/4\) 。

代码
下面的代码演示了使用ATtiny88的SPI模块与W25Q32 Flash模块进行通信,读取Flash的ID信息。源文件的组织结构如下:
.
├── Makefile
├── inc
│ ├── serial.h
│ └── serial_stdio.h
└── src
├── main.c
├── serial.c
└── serial_stdio.c
src/main.c 源文件的代码如下:
#include <stdint.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <serial_stdio.h>
static void spi_setup(void);
static uint8_t spi_read_and_write(uint8_t data);
static void w25qxx_read_device_id(void *id, uint8_t n);
static void w25qxx_read_manufacturer_device_id(void *id, uint8_t n);
static void w25qxx_read_unique_id(void *id, uint8_t n);
static void w25qxx_read_jedec_id(void *id, uint8_t n);
int main(void)
{
cli();
stdio_setup(); // initialize stdio and redirect it to serial
spi_setup(); // initialize spi module
sei();
printf("=================================\r\n");
// read device id of spi flash
uint8_t buf[8];
w25qxx_read_device_id(buf, 1);
printf("device id: 0x%02X.\r\n", buf[0]);
// read manufacturer and device id of spi flash
w25qxx_read_manufacturer_device_id(buf, 2);
printf("manufacturer & device id: 0x%02X%02X.\r\n", buf[0], buf[1]);
// read unique id of spi flash
w25qxx_read_unique_id(buf, 8);
printf("unique id: 0x");
for (uint8_t i = 0; i < 8; i++) {
printf("%02X", buf[i]);
}
printf(".\r\n");
// read jedec id of spi flash
w25qxx_read_jedec_id(buf, 3);
printf("jedec id: 0x%02X%02X%02X.\r\n", buf[0], buf[1], buf[2]);
for (;;);
}
static void spi_setup(void)
{
// initialize gpios
// PB2 -> SS
// PB3 -> MOSI
// PB4 -> MISO
// PB5 -> SCK
DDRB |= _BV(DDB2) | _BV(DDB3) | _BV(DDB5);
PORTB |= _BV(PORTB2) | _BV(PORTB3) | _BV(PORTB5);
// enable spi, msb first, master mode, mode 3, prescaler = 64
SPCR = _BV(SPE) | _BV(MSTR) | _BV(CPOL) | _BV(CPHA) | _BV(SPR1) | _BV(SPR0);
SPSR = _BV(SPI2X);
}
static uint8_t spi_read_and_write(uint8_t data)
{
SPDR = data;
while (!(SPSR & _BV(SPIF)));
return SPDR;
}
static void w25qxx_read_device_id(void *id, uint8_t n)
{
if (n > 1) {
n = 1;
}
PORTB &= ~_BV(PORTB2);
spi_read_and_write(0xAB);
spi_read_and_write(0xFF);
spi_read_and_write(0xFF);
spi_read_and_write(0xFF);
while (n--) {
*(uint8_t *)id++ = spi_read_and_write(0xFF);
}
PORTB |= _BV(PORTB2);
}
static void w25qxx_read_manufacturer_device_id(void *id, uint8_t n)
{
if (n > 2) {
n = 2;
}
PORTB &= ~_BV(PORTB2);
spi_read_and_write(0x90);
spi_read_and_write(0xFF);
spi_read_and_write(0xFF);
spi_read_and_write(0x00);
while (n--) {
*(uint8_t *)id++ = spi_read_and_write(0xFF);
}
PORTB |= _BV(PORTB2);
}
static void w25qxx_read_unique_id(void *id, uint8_t n)
{
if (n > 8) {
n = 8;
}
PORTB &= ~_BV(PORTB2);
spi_read_and_write(0x4B);
spi_read_and_write(0xFF);
spi_read_and_write(0xFF);
spi_read_and_write(0xFF);
spi_read_and_write(0xFF);
while (n--) {
*(uint8_t *)id++ = spi_read_and_write(0xFF);
}
PORTB |= _BV(PORTB2);
}
static void w25qxx_read_jedec_id(void *id, uint8_t n)
{
if (n > 3) {
n = 3;
}
PORTB &= ~_BV(PORTB2);
spi_read_and_write(0x9F);
while (n--) {
*(uint8_t *)id++ = spi_read_and_write(0xFF);
}
PORTB |= _BV(PORTB2);
}
编译并下载程序到ATtiny88,连接好串口,可以观察串口的输出如下:

参考资料
ATtiny88初体验(六):SPI的更多相关文章
- Spring Cloud Alibaba 初体验(六) Seata 及结合 MyBatis 与 MyBatis-Plus 的使用
一.下载与运行 本文使用 Seata 1.1.0:https://github.com/seata/seata/releases Windows 环境下双击 bin/seata-server.bat ...
- win7升win10,初体验
跟宿舍哥们聊着聊着,聊到最近发布正式版的win10,听网上各种评论,吐槽,撒花的,想想,倒不如自己升级一下看看,反正不喜欢还可以还原.于是就开始了win10的初体验了,像之前装黑苹果双系统一样的兴奋, ...
- ASP.NET2.0组件控件开发视频 初体验
原文:ASP.NET2.0组件控件开发视频 初体验 ASP.NET2.0组件控件开发视频 初体验 录了视频,质量不是很好,大家体验下.我会重新录制的 如果不清楚,可以看看http://v.youku. ...
- SpringBoot初体验及原理解析
一.前言 上篇文章,我们聊到了SpringBoot得以实现的幕后推手,这次我们来用SpringBoot开始HelloWorld之旅.SpringBoot是Spring框架对“约定大于配置(Conv ...
- ARKit从入门到精通(1)-ARKit初体验
ARKit从入门到精通(1)-ARKit初体验 转载自:http://blog.csdn.net/u013263917/article/details/72903174 该系列文章共十篇,笔者将由易到 ...
- Ignite缓存管理初体验
Ignite缓存管理初体验:ignite服务端配置,大家可以用参考官方进行配置(或者使用默认配置也可以). 本文中的ignite使用版本是1.7,与spring结合使用.maven依赖配置 ignit ...
- Node.js 网页瘸腿爬虫初体验
延续上一篇,想把自己博客的文档标题利用Node.js的request全提取出来,于是有了下面的初哥爬虫,水平有限,这只爬虫目前还有点瘸腿,请看官你指正了. // 内置http模块,提供了http服务器 ...
- 【全面解禁!真正的Expression Blend实战开发技巧】第七章 MVVM初体验-在DataGrid行末添加按钮
原文:[全面解禁!真正的Expression Blend实战开发技巧]第七章 MVVM初体验-在DataGrid行末添加按钮 博客更新较慢,先向各位读者说声抱歉.这一节讲解的依然是开发中经常遇到的一种 ...
- 【Python3爬虫】爬取美女图新姿势--Redis分布式爬虫初体验
一.写在前面 之前写的爬虫都是单机爬虫,还没有尝试过分布式爬虫,这次就是一个分布式爬虫的初体验.所谓分布式爬虫,就是要用多台电脑同时爬取数据,相比于单机爬虫,分布式爬虫的爬取速度更快,也能更好地应对I ...
- 【Python3爬虫】学习分布式爬虫第一步--Redis分布式爬虫初体验
一.写在前面 之前写的爬虫都是单机爬虫,还没有尝试过分布式爬虫,这次就是一个分布式爬虫的初体验.所谓分布式爬虫,就是要用多台电脑同时爬取数据,相比于单机爬虫,分布式爬虫的爬取速度更快,也能更好地应对I ...
随机推荐
- 【Linux】(小白向)详解VirtualBox网络配置-配置Linux网络
本文时间 2023-05-18 作者:sugerqube漆瓷 本文面向新手,重在理解会舍弃不少精密的理论,还请大佬们见谅. 本文目标:成功使用ssh工具登录linux,同时linux能连接外网. 网络 ...
- 「P3」试下1个半月能不能水出个毕设
前言 虽然说标题上写的时间是1个半月,但是实际上,真正开始行动的时间应该1个月都没有.之前都是在公司上班没活的时候干的.现在请了个长假,专门来做毕业设计:预计5月前能做完整个毕业设计,然后劳动节放假期 ...
- Redis - 二进制位数组
简介 Redis 使用字符串对象来表示位数组,因为字符串对象使用的 SDS 数据结构是二进制安全的,所以程序可以直接使用 SDS 结构来保存位数组,并使用 SDS 结构的操作函数来处理位数组. 在 S ...
- vue 一键导出数据为excel文件并附带样式 十分简单
自入行以来我就一直疑惑一个问题,导出excel为什么总是搞的很复杂,包括网上的教程,屎里淘金,非常耗费精力.今天刚好业务需要,整理一个简单明了的由vue前端导出的版本出来. 开始: #1.添加xlsx ...
- SignalR+Hangfire 实现后台任务队列和实时通讯
SignalR+Hangfire 实现后台任务队列和实时通讯 1.简介: SignalR是一个.NET的开源框架,SignalR可使用Web Socket, Server Sent Events 和 ...
- DHCP配置;DHCP Relay配置
目录 DHCP 配置 实验拓扑 实验需求 实验步骤 1. 基于全局地址池的DHCP服务器给客户端分配IP地址 DHCP server 上配置如下 2. 在PC1上设置为DHCP自动获取方式,ipcon ...
- 天下苦 Spring 久矣,Solon v2.3.3 发布
Solon 是什么框架? 一个,Java 新的生态型应用开发框架.它从零开始构建,有自己的标准规范与开放生态(全球第二级别的生态).与其他框架相比,它解决了两个重要的痛点:启动慢,费资源. 解决痛点? ...
- 你的专属音乐生成器「GitHub 热点速览」
如果你制作视频,一定会碰到配乐的问题.虽然网上找的一些免费配乐能勉强满足需求,但是如果有个专属的配乐生成器,根据你的视频画面生成对应配乐是不是不错呢?audiocraft 也许能帮助你,把相关画面用文 ...
- 前端vue简单好用的上拉加载下拉刷新组件,支持列表分页 本地分页
前端vue简单好用的上拉加载下拉刷新组件,支持列表分页 本地分页, 下载完整代码请访问uni-app插件市场地址: https://ext.dcloud.net.cn/plugin?id=12942 ...
- GPU技术在大规模数据集处理和大规模计算中的应用
目录 GPU 技术在大规模数据集处理和大规模计算中的应用 随着深度学习在人工智能领域的快速发展,大规模数据处理和大规模计算的需求日益增长.GPU(图形处理器)作为现代计算机的重要部件,被广泛应用于这些 ...