STC8的硬件IIC怎么样
请教一下,STC8系列的单片机硬件I2C怎么样?计划使用STC8G1K08A,用来给其他IC加载初始化配置,需要发送的内容大概五百多字节。
好,够用
可以用 好用
//20.5.6 测试 I2C 从机模式代码的主机代码
//测试工作频率为 11.0592MHz
#include "reg51.h"
#include "intrins.h"
sfr P_SW2 = 0xba;
#define I2CCFG (*(unsigned char volatile xdata *)0xfe80)
#define I2CMSCR (*(unsigned char volatile xdata *)0xfe81)
#define I2CMSST (*(unsigned char volatile xdata *)0xfe82)
#define I2CSLCR (*(unsigned char volatile xdata *)0xfe83)
#define I2CSLST (*(unsigned char volatile xdata *)0xfe84)
#define I2CSLADR (*(unsigned char volatile xdata *)0xfe85)
#define I2CTXD (*(unsigned char volatile xdata *)0xfe86)
#define I2CRXD (*(unsigned char volatile xdata *)0xfe87)
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
sbit SDA = P3^3;
sbit SCL = P3^2;
void Wait()
{
while (!(I2CMSST & 0x40));
I2CMSST &= ~0x40;
}
void Start()
{
I2CMSCR = 0x01; //发送START命令
Wait();
}
void SendData(char dat)
{
I2CTXD = dat; //写数据到数据缓冲区
I2CMSCR = 0x02; //发送SEND命令
Wait();
}
void RecvACK()
{
I2CMSCR = 0x03; //发送读ACK命令
Wait();
}
char RecvData()
{
I2CMSCR = 0x04; //发送RECV命令
Wait();
return I2CRXD;
}
void SendACK()
{
I2CMSST = 0x00; //设置ACK信号
I2CMSCR = 0x05; //发送ACK命令
Wait();
}
void SendNAK()
{
I2CMSST = 0x01; //设置NAK信号
I2CMSCR = 0x05; //发送ACK命令
Wait();
}
void Stop()
{
I2CMSCR = 0x06; //发送STOP命令
Wait();
}
void Delay()
{
int i;
for (i=0; i<3000; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
//( STC8G1K08-8Pin 系列、 STC8G1K08A 系列)
P_SW2 = 0x00; //SCL/P3.2, SDA/P3.3
//P_SW2 = 0x10; //SCL_2/P5.4, SDA_2/P5.5
//因传统8051的SFR地址空间有限,新增的SFR位于xdata区域(XSFR),必须先打开EAXFR才能访问 XSFR和XDATA共用地址,
//只有访问62.5K以上的XDATA时才需要关闭EAXFR 现有型号,只要不是扩展了片外64K SRAM(外接并口SRAM芯片),
//初始化时果断先打开EAXFR,并且不需要再关闭,不要犹豫!
P_SW2 |= 0x80; //外设端口切换寄存器 2 EAXFR=1
//可以在上电系统初始化时将 EAXFR 寄存器设置为 1(例如: P_SW2 |= 0x80;),后续一直保持为 1 不用再修改,即可正常访问 XFR 区域。
I2CCFG = 0xe0; //使能I2C主机模式
I2CMSST = 0x00;
Start(); //发送起始命令
SendData(0x5a); //发送设备地址(010_1101B)+写命令(0B)
RecvACK();
SendData(0x00); //发送存储地址
RecvACK();
SendData(0x12); //写测试数据1
RecvACK();
SendData(0x78); //写测试数据2
RecvACK();
Stop(); //发送停止命令
Start(); //发送起始命令
SendData(0x5a); //发送设备地址(010_1101B)+写命令(0B)
RecvACK();
SendData(0x00); //发送存储地址高字节
RecvACK();
Start(); //发送起始命令
SendData(0x5b); //发送设备地址(010_1101B)+读命令(1B)
RecvACK();
P0 = RecvData(); //读取数据1
SendACK();
P2 = RecvData(); //读取数据2
SendNAK();
Stop(); //发送停止命令
//P_SW2 = 0x00; //后续一直保持为 1 不用再修改
//若用户不使用外部扩展 RAM 或者外部扩展 RAM 的最大地址不超过 0FA00H(例如只外扩 32K RAM),
while (1);
}
//20.5.4 I2C 从机模式(中断方式)
//测试工作频率为 11.0592MHz
#include "reg51.h"
#include "intrins.h"
sfr P_SW2 = 0xba;
#define I2CCFG (*(unsigned char volatile xdata *)0xfe80)
#define I2CMSCR (*(unsigned char volatile xdata *)0xfe81)
#define I2CMSST (*(unsigned char volatile xdata *)0xfe82)
#define I2CSLCR (*(unsigned char volatile xdata *)0xfe83)
#define I2CSLST (*(unsigned char volatile xdata *)0xfe84)
#define I2CSLADR (*(unsigned char volatile xdata *)0xfe85)
#define I2CTXD (*(unsigned char volatile xdata *)0xfe86)
#define I2CRXD (*(unsigned char volatile xdata *)0xfe87)
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
sbit SDA = P3^3;
sbit SCL = P3^2;
bit isda; //设备地址标志
bit isma; //存储地址标志
unsigned char addr;
unsigned char pdata buffer;
void I2C_Isr() interrupt 24
{
_push_(P_SW2);
P_SW2 |= 0x80;
if (I2CSLST & 0x40)
{
I2CSLST &= ~0x40; //处理START事件
}
else if (I2CSLST & 0x20)
{
I2CSLST &= ~0x20; //处理RECV事件
if (isda)
{
isda = 0; //处理RECV事件(RECV DEVICE ADDR)
}
else if (isma)
{
isma = 0; //处理RECV事件(RECV MEMORY ADDR)
addr = I2CRXD;
I2CTXD = buffer;
}
else
{
buffer = I2CRXD; //处理RECV事件(RECV DATA)
}
}
else if (I2CSLST & 0x10)
{
I2CSLST &= ~0x10; //处理SEND事件
if (I2CSLST & 0x02)
{
I2CTXD = 0xff; //接收到NAK则停止读取数据
}
else
{
I2CTXD = buffer[++addr]; //接收到ACK则继续读取数据
}
}
else if (I2CSLST & 0x08)
{
I2CSLST &= ~0x08; //处理STOP事件
isda = 1;
isma = 1;
}
_pop_(P_SW2);
}
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P_SW2 = 0x80; //将 EAXFR 寄存器设置为 1 ,即可正常访问 XFR 区域。
I2CCFG = 0x81; //使能I2C从机模式
I2CSLADR = 0x5a; //设置从机设备地址寄存器I2CSLADR=0101_1010B
//即I2CSLADR=010_1101B,MA=0B。
//由于MA为0,主机发送的的设备地址必须与
//I2CSLADR相同才能访问此I2C从机设备。
//主机若需要写数据则要发送5AH(0101_1010B)
//主机若需要读数据则要发送5BH(0101_1011B)
I2CSLST = 0x00;
I2CSLCR = 0x78; //使能从机模式中断
EA = 1;
isda = 1; //用户变量初始化
isma = 1;
addr = 0;
I2CTXD = buffer;
while (1);
}
//20.5.5 I2C 从机模式(查询方式)
//测试工作频率为 11.0592MHz
#include "reg51.h"
#include "intrins.h"
sfr P_SW2 = 0xba;
#define I2CCFG (*(unsigned char volatile xdata *)0xfe80)
#define I2CMSCR (*(unsigned char volatile xdata *)0xfe81)
#define I2CMSST (*(unsigned char volatile xdata *)0xfe82)
#define I2CSLCR (*(unsigned char volatile xdata *)0xfe83)
#define I2CSLST (*(unsigned char volatile xdata *)0xfe84)
#define I2CSLADR (*(unsigned char volatile xdata *)0xfe85)
#define I2CTXD (*(unsigned char volatile xdata *)0xfe86)
#define I2CRXD (*(unsigned char volatile xdata *)0xfe87)
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
sbit SDA = P3^3;
sbit SCL = P3^2;
bit isda; //设备地址标志
bit isma; //存储地址标志
unsigned char addr;
unsigned char pdata buffer;
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P_SW2 = 0x80; //将 EAXFR 寄存器设置为 1 ,即可正常访问 XFR 区域。
I2CCFG = 0x81; //使能I2C从机模式
I2CSLADR = 0x5a; //设置从机设备地址寄存器I2CSLADR=0101_1010B
//即I2CSLADR=010_1101B,MA=0B。
//由于MA为0,主机发送的的设备地址必须与
//I2CSLADR相同才能访问此I2C从机设备。
//主机若需要写数据则要发送5AH(0101_1010B)
//主机若需要读数据则要发送5BH(0101_1011B)
I2CSLST = 0x00;
I2CSLCR = 0x00; //禁止从机模式中断
isda = 1; //用户变量初始化
isma = 1;
addr = 0;
I2CTXD = buffer;
while (1)
{
if (I2CSLST & 0x40)
{
I2CSLST &= ~0x40; //处理START事件
}
else if (I2CSLST & 0x20)
{
I2CSLST &= ~0x20; //处理RECV事件
if (isda)
{
isda = 0; //处理RECV事件(RECV DEVICE ADDR)
}
else if (isma)
{
isma = 0; //处理RECV事件(RECV MEMORY ADDR)
addr = I2CRXD;
I2CTXD = buffer;
}
else
{
buffer = I2CRXD; //处理RECV事件(RECV DATA)
}
}
else if (I2CSLST & 0x10)
{
I2CSLST &= ~0x10; //处理SEND事件
if (I2CSLST & 0x02)
{
I2CTXD = 0xff; //接收到NAK则停止读取数据
}
else
{
I2CTXD = buffer[++addr]; //接收到ACK则继续读取数据
}
}
else if (I2CSLST & 0x08)
{
I2CSLST &= ~0x08; //处理STOP事件
isda = 1;
isma = 1;
}
}
}
几个I2C例程供参考:
https://www.stcaimcu.com/thread-4612-1-1.html
https://www.stcaimcu.com/thread-4613-1-1.html
https://www.stcaimcu.com/thread-4698-1-1.html
页:
[1]