这是使用STC32G12K128的I2C外设读取SHT40数据的代码
#include "COMM/stc.h"
#include "stdio.h"
#include "usart2.h"
#include "iic.h"
#define SHT40_ADDR 0x88
#define SHT40_CMD_HIGH_PRECISION 0xFD
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
void sys_init();//函数声明
void delay_ms(u16 ms);//unsigned int
bit TIM_10MS_Flag;//10ms的标志位
u16 Tme_CountDown = 0;//全局变量
u8 dat[32];
void sht40_setPrecision(void) {
// 发送高精度测量命令
IIC_START();
IIC_SENDBYTE(SHT40_ADDR);
IIC_WAITACK();
// 精度指令
IIC_SENDBYTE(SHT40_CMD_HIGH_PRECISION);
IIC_WAITACK();
IIC_STOP();
}
// 读取温湿度数据
void sht40_read(u8 *dat) {
int i = 0;
sht40_setPrecision();
delay_ms(10);
IIC_START();
// 读数据指令的第一个字节:地址
IIC_SENDBYTE((u8)(SHT40_ADDR+0x01));
IIC_WAITACK();
// 读取6个字节的数据
for (i=0; i<6; i++) {
dat[i] = IIC_READBYTE();
if (i<5) {
IIC_SENDACK();
}
}
IIC_SENDNACK();
IIC_STOP();
}
void sys_init() {
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
P3M0 = 0x00;
P3M1 = 0x00;
P3M0 &= ~0x03;
P3M1 |= 0x03;
//设置USB使用的时钟源
IRC48MCR = 0x80; //使能内部48M高速IRC
while (!(IRC48MCR & 0x01)); //等待时钟稳定
USBCLK = 0x00;//使用CDC功能需要使用这两行,HID功能禁用这两行。
USBCON = 0x90;
}
void delay_ms(u16 ms) {
u16 i;
do {
i = MAIN_Fosc/6000;
while(--i);
} while(--ms);
}
void main() {
char str[30];
int i=0;
float t=0;
float h=0;
u16 t0;
u16 h0;
sys_init();// IO口初始化
UART2_config(2); // 选择波特率, 2: 使用Timer2做波特率, 其它值: 无效.
IIC_Init();// iic初始化
EA = 1;// CPU开放中断,打开总中断。
while(1) {
//-----------------------读取数据-----------------------
sht40_read(dat);
for (i=0; i<6; i++) {
PrintChar(dat[i]);
}
PrintString2("\r\n");
sprintf(str,"Dat=%02X\t%02X\t%02X\t%02X\t%02X\t%02X\r\n", dat[0], dat[1], dat[2], dat[3], dat[4], dat[5]);
PrintString2(str);
t0 = (u16)(dat[0]*256 + dat[1]);
h0 = (u16)(dat[3]*256 + dat[4]);
t= 175.0 * t0 / 65535.0 - 45.0;
h= 125.0 * h0 / 65535.0 - 6.0;
sprintf(str,"Dat=%u\t %u\t T:%2.2f,H:%2.2f\r\n",t0, h0, t, h);
PrintString2(str);
delay_ms(3000);
}
}I2C外设映射到P2.4,P2.5上,速度为900KHz左右。
// IIC初始化
void IIC_Init(){
I2C_S1 = 0;//设置IIC的引脚,S1S0=01 : P2.5=scl, P2.4=sda
I2C_S0 = 1;
//I2CCFG = 0xE0;//设置速度和使能IIC,速度200K
//I2CCFG = 0xC8;//设置速度和使能IIC,速度500K
//I2CCFG = 0xC4;//设置速度和使能IIC,速度800K
I2CCFG = 0xC3;//设置速度和使能IIC,速度900K
I2CMSST = 0;//清空主机状态
}串口调试映射到P4.6,P4.7上,波特率115200,n,8,1。
void UART2_config(u8 brt) {
if(brt == 2) {
SetTimer2Baudraye(Baudrate2);
S2CFG |= 0x01; //使用串口2时,W1位必需设置为1,否则可能会产生不可预期的错误
S2CON = (S2CON & 0x3f) | 0x40; //UART2模式, 0x00: 同步移位输出, 0x40: 8位数据,可变波特率, 0x80: 9位数据,固定波特率, 0xc0: 9位数据,可变波特率
ES2 = 1; //允许中断
S2REN = 1; //允许接收
S2_S = 1; //UART2 switch to: 0: P1.0 P1.1, 1: P4.6 P4.7
B_TX2_Busy = 0;
TX2_Cnt = 0;
RX2_Cnt = 0;
}
}
void UART2_int (void) interrupt 8 {
// 如果接受到数据
if(S2RI) {
S2RI = 0; //Clear Rx flag
RX2_Buffer[RX2_Cnt] = S2BUF;
if( RX2_Buffer[RX2_Cnt]== '\n' ) {
if( RX2_Buffer[RX2_Cnt-1]== '\r' ) {
Rec_Flag = 1;
}
RX2_Cnt = 0;
} else {
RX2_Cnt++;
}
}
if(S2TI) {
S2TI = 0; //Clear Tx flag
B_TX2_Busy = 0;
}
}测试结果:

I2C总线时序数据:



在进行数据处理的过程中,犯了一些低级错误,表现在:
1、声明变量时,按照了计算机软件编程方式,声明两个类型相同的变量时,使用了下面这种形式
u16 a, b;
结果后面的处理过程中,数据总是不对。应该改成:
u16 a;
u16 b;
2、使用sprintf格式化数据时,使用%d格式化u16数据,结果导致不正常,实际上用应该使用%u。
查了下相关资料,有如下说明:

我要赚赏金
