ATtiny88初体验(七):TWI

TWI模块介绍

ATtiny88的TWI模块兼容Phillips I2C以及SMBus,支持主从模式,支持7bit地址,最大允许128个不同的从机地址。在多主机模式下,支持总线仲裁。从机模式下的数据速率高达400kHz,且从机地址可编程。在睡眠模式下,支持地址识别唤醒。

注意:为了使用TWI模块, PRR 寄存器中的 PRTWI 位必须设为0。

数据位传输:

开始和停止条件:

地址帧格式:

数据帧格式:

完整的传输过程:

普通模式时钟频率:

\[f_{SCL} = \frac{clk_{I/O}}{16 + (2 \times TWBR \times TWPS)}
\]

高速模式时钟频率:

\[f_{SCL} = \frac{clk_{TWIHS}}{16 + (2 \times TWBR \times TWPS)}
\]

其中, \(clk_{I/O}\) 为分频后的系统时钟, \(clk_{TWIHS}\) 为系统时钟。

注意:主机模式下, TWBR 值不能低于10。

下图展现了一个典型传输过程中,应用程序如何与TWI模块交互的。

ATtiny88的TWI拥有四种模式:Master Transmitter、Master Receiver、Slave Transmitter、Slave Receiver。

Master Transmitter模式下的状态码:

Master Receiver模式下的状态码:

Slave Receiver模式下的状态码:

Slave Transmitter模式下的状态码:

其他状态码:

多主机仲裁过程及状态码:

寄存器

  • TWBR[7:0] :分频系数,在主机模式下不能低于10。

  • TWINT :TWI中断标志,必须写1清除(不会执行完中断自动清除),在清除前,必须完成对 TWAR 寄存器、 TWSR 寄存器、 TWDR 寄存器的操作。 TWINT 置位期间,SCL线始终保持低电平。
  • TWEA :写1使能应答。
  • TWSTA :写1产生START信号,在START信号传输完成后必须手动清除该位。
  • TWSTO :写1产生STOP信号,该位会自动清除。从机状态下,设置该位可以从错误状态中恢复。
  • TWWC :写冲突标志,在 TWINT 位为1时写 TWDR 寄存器清除。
  • TWEN :写1使能TWI模块。
  • TWIE :写1使能TWI中断。

  • TWS :TWI状态码。
  • TWPS :TWI分频。

  • TWA[6:0] :TWI从机地址。
  • TWGCE :写1使能General Call。

  • TWAM[6:0] :TWI地址掩码,设为1将忽略对应位的匹配。

  • TWHS :写1使能TWI高速模式。

代码

下面的代码展示了如何使用ATtiny88的TWI模块与SSD1306 OLED进行通信刷屏。

源文件的组织结构如下:

.
├── 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> #define OLED_ADDR 0x3C
#define oled_write_command(cmd) oled_write_byte(0, cmd)
#define oled_write_data(data) oled_write_byte(1, data) static void oled_setup(void);
static void oled_write_byte(uint8_t dc, uint8_t data);
static void oled_fill(uint8_t color); int main(void)
{
cli();
stdio_setup(); // initialize stdio and redirect it to serial
oled_setup(); // initialize oled
sei(); static const uint8_t colors[] = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02
};
uint8_t i = 0; for (;;) {
oled_fill(colors[i]);
i = (i + 1) % sizeof(colors);
}
} static void oled_setup(void)
{
static const uint8_t cmds[] = {
0xAE, 0xD5, 0x80, 0xA8, 0x3F,
0xD3, 0x00, 0x40, 0x8D, 0x14,
0x20, 0x00, 0xA1, 0xC8, 0xDA,
0x12, 0x81, 0xEF, 0xD9, 0xF1,
0xDB, 0x30, 0xA4, 0xA6, 0xAF
}; TWSR = 0x00; // TWPS = 1
TWBR = 12; // TWBR = 12, freq = 16MHz / (16 + 2 * 12 * 1) = 400KHz
TWHSR = 0x00; // disable high speed mode for (uint8_t i = 0; i < sizeof(cmds); i++) {
oled_write_command(cmds[i]);
}
oled_fill(0x00);
} static void oled_write_byte(uint8_t dc, uint8_t data)
{
// transmit START condition
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
while (!(TWCR & _BV(TWINT))); // transmit SLA+W
TWDR = OLED_ADDR << 1;
TWCR = _BV(TWINT) | _BV(TWEN);
while (!(TWCR & _BV(TWINT))); // transmit control byte
TWDR = dc ? 0x40 : 0x00;
TWCR = _BV(TWINT) | _BV(TWEN);
while (!(TWCR & _BV(TWINT))); // transmit data byte
TWDR = data;
TWCR = _BV(TWINT) | _BV(TWEN);
while (!(TWCR & _BV(TWINT))); // transmit STOP condition
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
// Note that TWINT is NOT set after a STOP condition has been transmitted
} static void oled_fill(uint8_t color)
{
oled_write_command(0x21);
oled_write_command(0x00);
oled_write_command(0x7F);
oled_write_command(0x22);
oled_write_command(0x00);
oled_write_command(0x07); for (uint8_t i = 0; i < 128; i++) {
for (uint8_t j = 0; j < 8; j++) {
oled_write_data(color);
}
}
}

参考资料

  1. ATtiny88 Datasheet

ATtiny88初体验(七):TWI的更多相关文章

  1. python--爬虫入门(七)urllib库初体验以及中文编码问题的探讨

    python系列均基于python3.4环境 ---------@_@? --------------------------------------------------------------- ...

  2. 【全面解禁!真正的Expression Blend实战开发技巧】第七章 MVVM初体验-在DataGrid行末添加按钮

    原文:[全面解禁!真正的Expression Blend实战开发技巧]第七章 MVVM初体验-在DataGrid行末添加按钮 博客更新较慢,先向各位读者说声抱歉.这一节讲解的依然是开发中经常遇到的一种 ...

  3. win7升win10,初体验

    跟宿舍哥们聊着聊着,聊到最近发布正式版的win10,听网上各种评论,吐槽,撒花的,想想,倒不如自己升级一下看看,反正不喜欢还可以还原.于是就开始了win10的初体验了,像之前装黑苹果双系统一样的兴奋, ...

  4. Node.js 网页瘸腿爬虫初体验

    延续上一篇,想把自己博客的文档标题利用Node.js的request全提取出来,于是有了下面的初哥爬虫,水平有限,这只爬虫目前还有点瘸腿,请看官你指正了. // 内置http模块,提供了http服务器 ...

  5. 深入Asyncio(三)Asyncio初体验

    Asyncio初体验 Asyncio在Python中提供的API很复杂,其旨在替不同群体的人解决不同的问题,也正是由于这个原因,所以很难区分重点. 可以根据asyncio在Python中的特性,将其划 ...

  6. python初体验 ——>>> 模拟体育竞技

    python初体验 ——>>> 模拟体育竞技 一.排球训练营 1. 简介: 模拟不同的两个队伍进行排球的模拟比赛. 2. 模拟原理: 通过输入各自的能力值(Ⅰ),模拟比赛的进行( P ...

  7. Serverless 初体验:快速开发与部署一个Hello World(Java版)

    昨天被阿里云的这个酷炫大屏吸引了! 我等85后开发者居然这么少!挺好奇到底什么鬼东西都是90.95后在玩?就深入看了一下. 这是一个关于Serverless的体验活动,Serverless在国内一直都 ...

  8. 省HVV初体验(edu)

    浙江省HVV初体验 此次参加的HVV是edu分会场,总的来说是对HVV有了一个初步的认识,了解实战和靶场练习之间存在的巨大鸿沟. 经历了这次HVV,对于渗透测试有了更深一步的理解.渗透测试的本质就是信 ...

  9. .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验

    不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...

  10. Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验

    Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...

随机推荐

  1. filler 抓取手机app的数据,手机wifi设置

    1.处于同一局域网下, 2.手机的代服务器修改为手动 3.代理服务器,名称为本机ip地址端口为8888,可以自己设置 4.fillder上面选择允许远程链接

  2. Helm实战案例一:在Kubernetes上使用Helm搭建Prometheus Operator监控

    目录 一.系统环境 二.前言 三.Prometheus Operator简介 四.helm安装prometheus-operator 五.配置prometheus-operator 5.1 修改gra ...

  3. 前端Vue自定义列表表格信息展示可用于商品规格参数展示

    前端Vue自定义列表表格信息展示可用于商品规格参数展示 , 下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=13131 效果图如下 ...

  4. 使用CosmosDB进行大规模数据的实时数据处理和流式传输

    目录 使用 Cosmos DB 进行大规模数据的实时数据处理和流式传输 背景介绍 文章目的 目标受众 技术原理及概念 基本概念解释 技术原理介绍 相关技术比较 实现步骤与流程 准备工作:环境配置与依赖 ...

  5. mysql处理delete后不释放磁盘空间

    myisam:optimize table table_name innodb:alter table table.name engine='innodb' 1. 问题描述在使用mysql的时候有时候 ...

  6. 【WALT】scale_exec_time() 代码详解

    @ 目录 [WALT]scale_exec_time() 代码详解 代码展示 代码逻辑: 为什么归一化? ⑴ 将 CPU cycles 转换为 CPU 当前频率 ⑵ 归一化 delta [WALT]s ...

  7. Java版人脸跟踪三部曲之三:编码实战

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 作为<Java版人脸跟踪三部曲> ...

  8. 通用权限系统-Dozer对象转换

    Dozer对象转换 介绍 Dozer 是一个 Java Bean 到 Java Bean 的映射器,它可以递归地将数据从一个对象复制到另一个.通常情况下,这些Java Beans将是不同的复杂类型. ...

  9. Vue基础技术之——数据绑定

    Vue数据大致绑定分为两类: 1.单向数据绑定(v-bind): 数据只能从data流向页面. 2.双向数据绑定(v-model):数据不仅能从data流向页面,还能从页面流向data. 话不多说,先 ...

  10. python学习笔记:继承与超类

    与java类似,继承的出现是为了提高代码的重复利用率,避免多次输入同样的代码.而超类就是java中的父类. 1.继承 要指定超类,可在定义类时,在class语句中的类名后加上超类名 基类就是超类,派生 ...