- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一 block MIPS 板 AR9341,我想在其中添加对 bit-banging i2c 总线的支持,而不是从内核启动。
我还有两个免费的GPIO,可用于SDA和SCL Pin。
我还阅读了一些文档和用户指南,了解如何在 u boot 中添加支持 bit-banging i2c 总线,但没有得到正确的想法。
有没有人有关于如何从 u boot 使用 GPIO 添加对 bit-banging i2c 总线的支持的文档或想法?
如果有人对此有想法,请尽快帮助我。
我尝试从 u boot 设置和清除两个 GPIO 和两个 LED,它工作正常,没有任何问题。现在我想将这两个 GPIos 连接为 SDA 和 SCL 线以进行软件位转换。
有没有人知道如何将 GPIO 配置为 SDA 和 SCL 引导代码本身的线路?
最佳答案
您可以尝试获取在 Wikipedia 上列出的 I²C Master 协议(protocol)的位碰撞示例并将其移植(适配)到您的 MCU 硬件。
以下是将 I²C 协议(protocol)作为 I²C 主设备进行位拆分的示例。该示例是用伪 C 语言编写的。它说明了之前描述的所有 I²C 功能(时钟延展、仲裁、开始/停止位、ack/nack)
// Hardware-specific support functions that MUST be customized:
#define I2CSPEED 100
void I2C_delay() { volatile int v; int i; for (i=0; i < I2CSPEED/2; i++) v; }
bool read_SCL(void); // Set SCL as input and return current level of line, 0 or 1
bool read_SDA(void); // Set SDA as input and return current level of line, 0 or 1
void clear_SCL(void); // Actively drive SCL signal low
void clear_SDA(void); // Actively drive SDA signal low
void arbitration_lost(void);
bool started = false; // global data
void i2c_start_cond(void) {
if (started) { // if started, do a restart cond
// set SDA to 1
read_SDA();
I2C_delay();
while (read_SCL() == 0) { // Clock stretching
// You should add timeout to this loop
}
// Repeated start setup time, minimum 4.7us
I2C_delay();
}
if (read_SDA() == 0) {
arbitration_lost();
}
// SCL is high, set SDA from 1 to 0.
clear_SDA();
I2C_delay();
clear_SCL();
started = true;
}
void i2c_stop_cond(void){
// set SDA to 0
clear_SDA();
I2C_delay();
// Clock stretching
while (read_SCL() == 0) {
// add timeout to this loop.
}
// Stop bit setup time, minimum 4us
I2C_delay();
// SCL is high, set SDA from 0 to 1
if (read_SDA() == 0) {
arbitration_lost();
}
I2C_delay();
started = false;
}
// Write a bit to I2C bus
void i2c_write_bit(bool bit) {
if (bit) {
read_SDA();
} else {
clear_SDA();
}
I2C_delay();
while (read_SCL() == 0) { // Clock stretching
// You should add timeout to this loop
}
// SCL is high, now data is valid
// If SDA is high, check that nobody else is driving SDA
if (bit && read_SDA() == 0) {
arbitration_lost();
}
I2C_delay();
clear_SCL();
}
// Read a bit from I2C bus
bool i2c_read_bit(void) {
bool bit;
// Let the slave drive data
read_SDA();
I2C_delay();
while (read_SCL() == 0) { // Clock stretching
// You should add timeout to this loop
}
// SCL is high, now data is valid
bit = read_SDA();
I2C_delay();
clear_SCL();
return bit;
}
// Write a byte to I2C bus. Return 0 if ack by the slave.
bool i2c_write_byte(bool send_start,
bool send_stop,
unsigned char byte) {
unsigned bit;
bool nack;
if (send_start) {
i2c_start_cond();
}
for (bit = 0; bit < 8; bit++) {
i2c_write_bit((byte & 0x80) != 0);
byte <<= 1;
}
nack = i2c_read_bit();
if (send_stop) {
i2c_stop_cond();
}
return nack;
}
// Read a byte from I2C bus
unsigned char i2c_read_byte(bool nack, bool send_stop) {
unsigned char byte = 0;
unsigned bit;
for (bit = 0; bit < 8; bit++) {
byte = (byte << 1) | i2c_read_bit();
}
i2c_write_bit(nack);
if (send_stop) {
i2c_stop_cond();
}
return byte;
}
然后您将需要TO DO上面代码中注释的所有地方,其中 1
或 0
设置在适当的 GPIO 上,取决于您在设备上选择了哪些。
顺便说一下,我已经为 MSP430 做了这个并且它有效。
您还可以在网上找到许多其他 MCU 的实现并进行比较,如下面的这些,但我将从上面的代码开始。
#include "pic16lf1947.h"
#include "PIC16_I2C_BITBANG.h"
#include "xc.h"
//....................................................................
// This function generates an I2C Start Condition
//....................................................................
void i2c_start(void)
{
unsigned int i;
SDA_TRIS = 1; // ensure SDA & SCL are high
SCL = 1;
SDA_TRIS = 0; // SDA = output
SDA = 0; // pull SDA low
for (i=0;i<2;i++) NOP();
SCL = 0; // pull SCL low
}
//....................................................................
// This function generates an I2C Stop Condition
//....................................................................
void i2c_stop(void)
{
unsigned int i;
SCL = 0; // ensure SCL is low
SDA_TRIS = 0; // SDA = output
SDA = 0; // SDA low
for (i=0;i<3;i++) NOP();
SCL = 1; // pull SCL high
SDA_TRIS = 1; // allow SDA to be pulled high
for (i=0;i<3;i++) NOP();
SCL=0; // ensure SCL is low
}
//.......................................................... AR9341..........
// Outputs a bit to the I2C bus
//....................................................................
void bit_out(unsigned char data)
{
unsigned int i;
SCL = 0; // ensure SCL is low
SDA_TRIS=0; // configure SDA as an output
SDA= (data>>7); // output the MSB
for (i=0;i<2;i++) NOP();
SCL = 1; // pull SCL high to clock bit
for (i=0;i<3;i++) NOP();
SCL = 0; // pull SCL low for next bit
}
//....................................................................
// Inputs a bit from the I2C bus
//....................................................................
void bit_in(unsigned char *data)
{
unsigned int i;
SCL = 0; // ensure SCL is low
SDA_TRIS = 1; // configure SDA as an input
SCL = 1; // bring SCL high to begin transfer
for (i=0;i<3;i++) NOP();
*data |= SDA; // input the received bit
SCL = 0; // bring SCL low again.
}
//....................................................................
// Writes a byte to the I2C bus
//....................................................................
unsigned char i2c_wr(unsigned char data)
{
unsigned char i; // loop counter
unsigned char ack; // ACK bit
ack = 0;
for (i = 0; i < 8; i++) // loop through each bit
{
bit_out(data); // output bit
data = data << 1; // shift left for next bit
}
bit_in(&ack); // input ACK bit
return ack;
}
//....................................................................
// Reads a byte from the I2C bus
//....................................................................
unsigned char i2c_rd(unsigned char ack)
{
unsigned char i; // loop counter
unsigned char ret=0; // return value
for (i = 0; i < 8; i++) // loop through each bit
{
ret = ret << 1; // shift left for next bit
bit_in(&ret); // input bit
}
bit_out(ack); // output ACK/NAK bit
return ret;
}
//.............................................................................
// Polls the bus for ACK from device
//.............................................................................
void ack_poll (unsigned char control)
{
unsigned char result=1;
while(result)
{
i2c_start(); // generate Restart condition
result=i2c_wr(control); // send control byte (WRITE command)
}
i2c_stop(); // generate Stop condition
}
// Port for the I2C
#define I2C_DDR DDRD
#define I2C_PIN PIND
#define I2C_PORT PORTD
// Pins to be used in the bit banging
#define I2C_CLK 0
#define I2C_DAT 1
#define I2C_DATA_HI()\
I2C_DDR &= ~ (1 << I2C_DAT);\
I2C_PORT |= (1 << I2C_DAT);
#define I2C_DATA_LO()\
I2C_DDR |= (1 << I2C_DAT);\
I2C_PORT &= ~ (1 << I2C_DAT);
#define I2C_CLOCK_HI()\
I2C_DDR &= ~ (1 << I2C_CLK);\
I2C_PORT |= (1 << I2C_CLK);
#define I2C_CLOCK_LO()\
I2C_DDR |= (1 << I2C_CLK);\
I2C_PORT &= ~ (1 << I2C_CLK);
void I2C_WriteBit(unsigned char c)
{
if (c > 0)
{
I2C_DATA_HI();
}
else
{
I2C_DATA_LO();
}
I2C_CLOCK_HI();
delay(1);
I2C_CLOCK_LO();
delay(1);
if (c > 0)
{
I2C_DATA_LO();
}
delay(1);
}
unsigned char I2C_ReadBit()
{
I2C_DATA_HI();
I2C_CLOCK_HI();
delay(1);
unsigned char c = I2C_PIN;
I2C_CLOCK_LO();
delay(1);
return (c >> I2C_DAT) & 1;
}
// Inits bitbanging port, must be called before using the functions below
//
void I2C_Init()
{
I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
I2C_CLOCK_HI();
I2C_DATA_HI();
delay(1);
}
// Send a START Condition
//
void I2C_Start()
{
// set both to high at the same time
I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
delay(1);
I2C_DATA_LO();
delay(1);
I2C_CLOCK_LO();
delay(1);
}
// Send a STOP Condition
//
void I2C_Stop()
{
I2C_CLOCK_HI();
delay(1);
I2C_DATA_HI();
delay(1);
}
// write a byte to the I2C slave device
//
unsigned char I2C_Write(unsigned char c)
{
for (char i = 0; i < 8; i++)
{
I2C_WriteBit(c & 128);
c <<= 1;
}
//return I2C_ReadBit();
return 0;
}
// read a byte from the I2C slave device
//
unsigned char I2C_Read(unsigned char ack)
{
unsigned char res = 0;
for (char i = 0; i < 8; i++)
{
res <<= 1;
res |= I2C_ReadBit();
}
if (ack > 0)
{
I2C_WriteBit(0);
}
else
{
I2C_WriteBit(1);
}
delay(1);
return res;
}
祝你好运!
关于linux - 如何在 MIPS 板的 u 引导代码中添加对 bit-banging i2c 总线的支持,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25278788/
已结束。 这个问题是 off-topic .它目前不接受答案。 想要改进这个问题? Update the question所以它是on-topic堆栈溢出。 关闭 9 年前。 社区在4个月前审核了是否
我想做一个简单的函数,它接受一个数据框和用户为该数据框中的两列提供的名称。目的是让它可以轻松地与 dplyr 管道一起工作。它将产生一个粘合字符串的字符向量: func % func(lastName
使用 !! 时出现奇怪的结果: ["a"].indexOf("b") === -1 // true !!(["a"].indexOf("b") === -1) //true !!["a"].index
我想知道是否有可能创建一个单一的方法,比如说 Array#square(它对数组中的元素进行平方),它允许一个可选的 bang !标识符? 这样,接收者是否被永久修改只取决于该方法是否被调用。例如,是
我在具有两个主要组的长数据库 (full_database) 上运行一个函数,我需要在每个组的多个子集上执行各种线性模型。 然后,我将 R^2、调整后的 R^2 和 p.value 提取到一个数据框中
如果您阅读 jQuery inArray 页面上的评论 here ,有一个有趣的声明: !!~jQuery.inArray(elm, arr) 现在,我相信双感叹号会将结果转换为 boolean 类型
如果您阅读 jQuery inArray 页面上的评论 here ,有一个有趣的声明: !!~jQuery.inArray(elm, arr) 现在,我相信双感叹号会将结果转换为 boolean 类型
我使用动态变量(例如 ID )作为引用列名的方法,该列名将根据我当时正在处理的基因而改变。然后我使用 case_when 内的 mutate 创建一个新列,该列的值取决于动态列。 我认为 !! (ba
我在文件中有以下内容 demo.py:-//可执行位设置 #!/usr/bin/python import os 我在终端中使用了命令 bash demo.py 并期望第一行由 bash 解释,它将文
当我想引用在该 shell 中执行的最后一个命令时,我习惯于在 bash 中键入 !!。 $ ls -la drwxr-xr-x 4 me wheel 136 Jan 19 2013
在这个代码示例中,taking_damage 方法之前的感叹号有什么用? if warrior.health < 20 && !taking_damage?(warrior) warrior
按照惯例,我们向任何改变其参数的函数名称添加爆炸字符 !,因此对于以下代码示例,我们是否应该向仿函数添加 !名字? mutable struct Foo a::Int end (foo::Fo
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 3年前关闭。 Improve t
如果没有对其参数进行硬编码,即 Me.VBProject.References!Excel,我无法成功使用 Bang (!) 运算符。在此示例中,Excel 引用是硬编码的。出于沮丧,我尝试了所有我能
我需要从 Java 小程序打开外部窗口。我怎样才能做到这一点而不使窗口成为小程序的子窗口?即使小程序关闭,我也需要窗口保持打开状态。我知道这是可以做到的。砰! Howdy 所做的正是我想要实现的目标。
这个问题已经有答案了: unnecessary exclamation marks(!)'s in HTML code (4 个回答) 已关闭 9 年前。 我遇到一个问题,我的 HTML 代码中出现
有没有办法检索 UNIX shell 将用于给定脚本的解释器的路径? (最好是在 Python API 中或作为 shell 命令)? 像这样使用: $ get_bang ./myscript.py
我有一个 Python 脚本 script.py,它已被定义为可执行文件并且以以下 sha-bang 开头: #!/usr/bin/env python -W all 但是当我从 shell 调用它时
是否可以在不使用赋值的情况下编写这段代码摘录? self.name = self.name.to_s.squeeze(' ').strip 我曾尝试使用 bang 版本的方法,但不能很好地使用,因为如
Airbnd suggests我这样做: !function() { // ... }(); 因为: This ensures that if a malformed module forgets
我是一名优秀的程序员,十分优秀!