- #include "I2C.h"
- //模拟IIC初始化
- void I2CInit(void)
- {
- SCL_out;
- SDA_out;
- }
- void I2C_delay(void)
- {
- mDelayuS(100);
- }
- int I2C_Start(void)
- {
- SDA_H;
- SDA_out;
- SCL_H;
- I2C_delay();
- if(!SDA_read)return 0; //SDA线为低电平则总线忙,退出
- SDA_L;
- I2C_delay();
- if(SDA_read) return 0; //SDA线为高电平则总线出错,退出
- SDA_L;
- I2C_delay();
- return 1;
- }
- void I2C_Stop(void)
- {
- SCL_L;
- I2C_delay();
- SDA_L;
- SDA_out;
- I2C_delay();
- SCL_H;
- I2C_delay();
- SDA_H;
- I2C_delay();
- }
- void I2C_Ack(void)
- {
- SCL_L;
- I2C_delay();
- SDA_L;
- SDA_out;
- I2C_delay();
- SCL_H;
- I2C_delay();
- I2C_delay();
- SCL_L;
- I2C_delay();
- }
- void I2C_NoAck(void)
- {
- SCL_L;
- I2C_delay();
- SDA_H;
- SDA_out;
- I2C_delay();
- SCL_H;
- I2C_delay();
- SCL_L;
- I2C_delay();
- }
- int I2C_WaitAck(void) //返回为:=1有ACK,=0无ACK
- {
- SCL_L;
- I2C_delay();
- I2C_delay();
- SDA_in;
- SCL_H;
- I2C_delay();
- I2C_delay();
- if(SDA_read)
- {
- SCL_L;
- return 0;
- }
- SCL_L;
- return 1;
- }
- void I2C_SendByte(u8 SendByte) //数据从高位到低位//
- {
- u8 i=8;
- SDA_out;
- while(i--)
- {
- SCL_L;
- I2C_delay();
- if(SendByte&0x80)
- SDA_H;
- else
- SDA_L;
- SendByte<<=1;
- I2C_delay();
- SCL_H;
- I2C_delay();
- I2C_delay();
- }
- SCL_L;
- }
- u8 I2C_ReadByte(void) //数据从高位到低位//
- {
- u8 i=8;
- u8 ReceiveByte=0;
- SDA_H;
- SDA_out;
- while(i--)
- {
- ReceiveByte<<=1;
- SCL_L;
- I2C_delay();
- I2C_delay();
- SCL_H;
- SDA_in;
- I2C_delay();
- I2C_delay();
- if(SDA_read)
- {
- ReceiveByte|=0x01;
- }
- }
- SCL_L;
- return ReceiveByte;
- }
- //7bit地址单字节写入*******************************************
- int I2C_7bit_Single_Write(u8 SlaveAddress, u8 REG_data)
- {
- if(!I2C_Start())return 0;
- I2C_SendByte(SlaveAddress); //发送设备地址+写信号//I2C_SendByte(((REG_Address & 0x0700) >>7) | SlaveAddress & 0xFFFE);//设置高起始地址+器件地址
- if(!I2C_WaitAck()){I2C_Stop(); return 0;}
- I2C_SendByte(REG_data);
- I2C_WaitAck(); I2C_Stop();
- return 1;
- }
- //7bit地址单字节读取*****************************************
- u8 I2C_7bit_Single_Read(u8 SlaveAddress)
- {
- unsigned char REG_data;
- if(!I2C_Start())return 0;
- I2C_SendByte(SlaveAddress); //I2C_SendByte(((REG_Address & 0x0700) >>7) | REG_Address & 0xFFFE);//设置高起始地址+器件地址
- if(!I2C_WaitAck())
- {
- I2C_Stop();
- return 0;
- }
- I2C_Start();
- I2C_SendByte(SlaveAddress+1);
- I2C_WaitAck();
- REG_data= I2C_ReadByte();
- I2C_NoAck();
- I2C_Stop();
- //return TRUE;
- return REG_data;
- }
- //7bit地址多字节读取*****************************************
- int I2C_7bit_Mult_Read(u8 SlaveAddress,u8 * ptChar,u8 size)
- {
- u8 i;
- if(size < 1)
- return 0;
- if(!I2C_Start())
- return 0;
- I2C_SendByte(SlaveAddress);
- if(!I2C_WaitAck())
- {
- I2C_Stop();
- return 0;
- }
- I2C_Start();
- I2C_SendByte(SlaveAddress+1);
- I2C_WaitAck();
- for(i=1;i<size; i++)
- {
- *ptChar++ = I2C_ReadByte();
- I2C_Ack();
- }
- *ptChar++ = I2C_ReadByte();
- I2C_NoAck();
- I2C_Stop();
- return 1;
- }
- //10bit地址单字节写入*******************************************
- int I2C_10bit_Single_Write(u8 SlaveAddress,u8 REG_Address,u8 REG_data)
- {
- if(!I2C_Start())return 0;
- I2C_SendByte(SlaveAddress); //发送设备地址+写信号//I2C_SendByte(((REG_Address & 0x0700) >>7) | SlaveAddress & 0xFFFE);//设置高起始地址+器件地址
- if(!I2C_WaitAck()){I2C_Stop(); return 0;}
- I2C_SendByte(REG_Address ); //设置低起始地址
- I2C_WaitAck();
- I2C_SendByte(REG_data);
- I2C_WaitAck();
- I2C_Stop();
- return 1;
- }
- //10bit地址单字节读取*****************************************
- u8 I2C_10bit_Single_Read(u8 SlaveAddress,u8 REG_Address)
- {
- unsigned char REG_data;
- if(!I2C_Start())return 0;
- I2C_SendByte(SlaveAddress); //I2C_SendByte(((REG_Address & 0x0700) >>7) | REG_Address & 0xFFFE);//设置高起始地址+器件地址
- if(!I2C_WaitAck())
- {
- I2C_Stop();
- return 0;
- }
- I2C_SendByte((u8) REG_Address); //设置低起始地址
- I2C_WaitAck();
- I2C_Start();
- I2C_SendByte(SlaveAddress+1);
- I2C_WaitAck();
- REG_data= I2C_ReadByte();
- I2C_NoAck();
- I2C_Stop();
- //return TRUE;
- return REG_data;
- }
- //10bit地址多字节读取*****************************************
- int I2C_10bit_Mult_Read(u8 SlaveAddress,u8 REG_Address,u8 * ptChar,u8 size)
- {
- u8 i;
- if(size < 1)
- return 0;
- if(!I2C_Start())
- return 0;
- I2C_SendByte(SlaveAddress);
- if(!I2C_WaitAck())
- {
- I2C_Stop();
- return 0;
- }
- I2C_SendByte(REG_Address);
- I2C_WaitAck();
- I2C_Start();
- I2C_SendByte(SlaveAddress+1);
- I2C_WaitAck();
- for(i=1;i<size; i++)
- {
- *ptChar++ = I2C_ReadByte();
- I2C_Ack();
- }
- *ptChar++ = I2C_ReadByte();
- I2C_NoAck();
- I2C_Stop();
- return 1;
- }
- /********************************** (C) COPYRIGHT *******************************
- * File Name : I2C.h
- * Author : WCH
- * Version : V1.0
- * Date : 2018/12/15
- * Description :
- *******************************************************************************/
- #ifndef __I2C_SOFT2_H__
- #define __I2C_SOFT2_H__
- #include "CH58x_common.h"
- #ifndef UINT8
- typedef unsigned char u8;
- #endif
- #define I2C_Pin_SCL GPIO_Pin_13
- #define I2C_Pin_SDA GPIO_Pin_12
- #define SCL_H GPIOB_SetBits( I2C_Pin_SCL )
- #define SCL_L GPIOB_ResetBits( I2C_Pin_SCL )
- #define SDA_H GPIOB_SetBits( I2C_Pin_SDA )
- #define SDA_L GPIOB_ResetBits( I2C_Pin_SDA )
- #define SCL_read GPIOB_ReadPortPin( I2C_Pin_SCL )
- #define SDA_read GPIOB_ReadPortPin( I2C_Pin_SDA )
- #define SCL_out GPIOB_ModeCfg(I2C_Pin_SCL, GPIO_ModeOut_PP_5mA)
- #define SCL_in GPIOB_ModeCfg(I2C_Pin_SCL, GPIO_ModeIN_PU)
- #define SDA_out GPIOB_ModeCfg(I2C_Pin_SDA, GPIO_ModeOut_PP_5mA)
- #define SDA_in GPIOB_ModeCfg(I2C_Pin_SDA, GPIO_ModeIN_PU)
-
- void I2CInit(void);
- int I2C_7bit_Single_Write(u8 SlaveAddress, u8 REG_data);
- u8 I2C_7bit_Single_Read(u8 Slave7BitAddress);
- int I2C_7bit_Mult_Read(u8 Slave7BitAddress,u8 * ptChar,u8 size);
- int I2C_10bit_Single_Write(u8 SlaveAddress,u8 REG_Address,u8 REG_data);
- u8 I2C_10bit_Single_Read(u8 SlaveAddress,u8 REG_Address);
- int I2C_10bit_Mult_Read(u8 SlaveAddress,u8 REG_Address,u8 * ptChar,u8 size);
- void I2C_delay(void);
- int I2C_Start(void);
- void I2C_Stop(void);
- void I2C_Ack(void);
- void I2C_NoAck(void);
- int I2C_WaitAck(void); //返回为:=1有ACK,=0无ACK
- void I2C_SendByte(u8 SendByte);
- u8 I2C_ReadByte(void); //数据从高位到低位//
- #endif
AHT30初始化
- void Init_AHTx0(uint8_t address)
- {
- uint8_t com[3]={0xBE,0x08,0x00};
- I2C_Write_Byte(address,com,3);
- printf("Init_AHTx0 OK\n");
- DelayMs(100);
- }
AHT30读写函数
- uint8_t I2C_Write_Byte(uint8_t addr_7bit ,uint8_t * data, uint8_t len)
- {
- uint8_t i=0;
- if(!I2C_Start())return 0;
- I2C_SendByte(addr_7bit<<1);
- if(!I2C_WaitAck()){I2C_Stop(); return 0;}
- for(i=0;i<len;i++)
- {
- I2C_SendByte(data[i]);
- I2C_WaitAck();
- }
- I2C_Stop();
- return 1;
- }
- uint8_t I2C_Read_Byte(uint8_t addr_7bit, uint8_t *data, uint8_t len)
- {
- uint8_t i=0;
- if(!I2C_Start())return 0;
- I2C_SendByte((addr_7bit<<1)|0x01); //bit7:1 为读
- if(!I2C_WaitAck()){I2C_Stop(); return 0;}
- while(i<(len-1))
- {
- data[i]= I2C_ReadByte();
- I2C_Ack();
- i++;
- }
- data[i]= I2C_ReadByte();
- I2C_NoAck();
- I2C_Stop();
- return 1;
- }
1.上电后要等待40ms,读取温湿度值之前, 首先要看状态字的校准使能位Bit[3]是否为 1(通过发送0x71可以获取一个字节的状态字),如果不为1,要发送0xBE命令(初始化),此命令参数有两个字节, 第一个字节为0x08,第二个字节为0x00。
- uint8_t com_init[3]={0xbe,0x08,0x00};//0xbe
2.直接发送 0xAC命令(触发测量),此命令参数有两个字节,第一个字节为 0x33,第二个字节为0x00。
3.等待75ms待测量完成,忙状态Bit[7]为0,然后可以读取六个字节(发0X71即可以读取)。
4.计算温湿度值。
- #define buff_size 6
- uint8_t com_read[3]={0xac,0x33,0x00};//0xac
- uint8_t temprature_buff[buff_size]={0x00,0x00,0x00,0x00,0x00,0x00};
- uint8_t t[20];
- void Get_tmprature(void)
- {
- I2C_Write_Byte(0x38,com_read,3);//开始测量
- DelayMs(150);
- I2C_Read_Byte(0x38,temprature_buff,buff_size);//读取温湿度
- Temp_Huimt(temprature_buff,t);
- }
- void Temp_Huimt(uint8_t * arr,uint8_t * t)
- {
- int32_t temp;
- int32_t humit;
- humit =arr[1];
- humit=((humit)<<8)|arr[2];
- humit=((humit)<<4)|(arr[3]>>4);
- temp =arr[3]&0x0f;
- temp=((temp)<<8)|arr[4];
- temp=((temp)<<8)|arr[5];
- sprintf(t,"h=%.2f,t=%.2f\n\r",(float)humit*100/1048576,(float)temp*200/1048576-50);
- }
蓝牙部分
创建server
创建特性
- <blockquote>#define SIMPLEPROFILE_CHAR1 0 // RW uint8_t - Profile Characteristic 1 value
- // Simple Profile Characteristic 4 Properties
- static uint8_t simpleProfileChar4Props = GATT_PROP_NOTIFY;
- // Characteristic 4 Value
- static uint8_t simpleProfileChar4[SIMPLEPROFILE_CHAR4_LEN] = {0};
- // Simple Profile Characteristic 4 Configuration Each client has its own
- // instantiation of the Client Characteristic Configuration. Reads of the
- // Client Characteristic Configuration only shows the configuration for
- // that client and writes only affect the configuration of that client.
- static gattCharCfg_t simpleProfileChar4Config[PERIPHERAL_MAX_CONNECTION];
- // Simple Profile Characteristic 4 User Description
- static uint8_t simpleProfileChar4UserDesp[] = "Characteristic 4\0";
添加server服务
- SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile
初始化蓝牙
- void Peripheral_Init()
- {
- //将事件的回调函数注册到 TMOS 中
- Peripheral_TaskID = TMOS_ProcessEventRegister(Peripheral_ProcessEvent);
- // Setup the GAP Peripheral Role Profile
- {
- uint8_t initial_advertising_enable = TRUE;
- uint16_t desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
- uint16_t desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
- // Set the GAP Role Parameters
- GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);//使能广播
- GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData);//扫描回复数据,数据格式要遵循广播数据格式
- GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);//扫描回复数据,数据格式要遵循广播数据格式
- GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t), &desired_min_interval);//最小连接间隔
- GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t), &desired_max_interval);//最大连接间隔
- }
- // Set the GAP Characteristics
- GGS_SetParameter(GGS_DEVICE_NAME_ATT, sizeof(attDeviceName), attDeviceName);//GAP特征,设备名称
- {
- uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;
- // Set advertising interval
- GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, advInt);
- GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, advInt);
- // Enable scan req notify
- GAP_SetParamValue(TGAP_ADV_SCAN_REQ_NOTIFY, ENABLE);
- }
- // Setup the GAP Bond Manager
- {
- uint32_t passkey = 0; // passkey "000000"
- uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
- uint8_t mitm = TRUE;
- uint8_t bonding = TRUE;
- uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
- GAPBondMgr_SetParameter(GAPBOND_PERI_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
- GAPBondMgr_SetParameter(GAPBOND_PERI_PAIRING_MODE, sizeof(uint8_t), &pairMode);
- GAPBondMgr_SetParameter(GAPBOND_PERI_MITM_PROTECTION, sizeof(uint8_t), &mitm);
- GAPBondMgr_SetParameter(GAPBOND_PERI_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
- GAPBondMgr_SetParameter(GAPBOND_PERI_BONDING_ENABLED, sizeof(uint8_t), &bonding);
- }
- // Initialize GATT attributes
- // GGS_AddService(GATT_ALL_SERVICES); // GAP
- // GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes
- // DevInfo_AddService(); // Device Information Service
- SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile
- // Setup the SimpleProfile Characteristic Values
- {
- uint8_t charValue1[SIMPLEPROFILE_CHAR1_LEN] = {1};
- uint8_t charValue2[SIMPLEPROFILE_CHAR2_LEN] = {2};
- uint8_t charValue3[SIMPLEPROFILE_CHAR3_LEN] = {3};
- uint8_t charValue4[SIMPLEPROFILE_CHAR4_LEN] = {4};
- uint8_t charValue5[SIMPLEPROFILE_CHAR5_LEN] = {1, 2, 3, 4, 5};
- uint8_t charValue6[SIMPLEPROFILE_CHAR6_LEN] = {'X','Q','-','B','L','E',0x0a};
- SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, SIMPLEPROFILE_CHAR1_LEN, charValue1);
- SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, SIMPLEPROFILE_CHAR2_LEN, charValue2);
- SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, SIMPLEPROFILE_CHAR3_LEN, charValue3);
- SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, SIMPLEPROFILE_CHAR4_LEN, charValue4);
- SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN, charValue5);
- SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR6, SIMPLEPROFILE_CHAR6_LEN, charValue6);
- }
- // Init Connection Item
- peripheralInitConnItem(&peripheralConnList);
- // Register callback with SimpleGATTprofile
- SimpleProfile_RegisterAppCBs(&Peripheral_SimpleProfileCBs);
- // Register receive scan request callback
- GAPRole_BroadcasterSetCB(&Broadcaster_BroadcasterCBs);
- // Setup a delayed profile startup
- tmos_set_event(Peripheral_TaskID, SBP_START_DEVICE_EVT); //启动Peripheral_TaskID任务下的SBP_START_DEVICE_EVT事件,其中tmos_set_event函数用于立刻执行某个事件
- tmos_start_reload_task(Peripheral_TaskID, TASK_1,3200);//启动一个循环事件
- tmos_start_reload_task(Peripheral_TaskID,TASK_TEMPRATURE,2200);//启动一个温湿度循环事件
- }
事件轮询
- uint16_t Peripheral_ProcessEvent(uint8_t task_id, uint16_t events)
- {
- // VOID task_id; // TMOS required parameter that isn't used in this function
- if(events & SYS_EVENT_MSG)
- {
- uint8_t *pMsg;
- if((pMsg = tmos_msg_receive(Peripheral_TaskID)) != NULL)
- {
- Peripheral_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
- // Release the TMOS message
- tmos_msg_deallocate(pMsg);
- }
- // return unprocessed events
- return (events ^ SYS_EVENT_MSG);
- }
- if(events & SBP_START_DEVICE_EVT)
- {
- // Start the Device
- GAPRole_PeripheralStartDevice(Peripheral_TaskID, &Peripheral_BondMgrCBs, &Peripheral_PeripheralCBs);
- return (events ^ SBP_START_DEVICE_EVT);
- }
- if(events & SBP_PERIODIC_EVT)
- {
- // Restart timer
- if(SBP_PERIODIC_EVT_PERIOD)
- {
- tmos_start_task(Peripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD);
- }
- // Perform periodic application task
- performPeriodicTask();
- return (events ^ SBP_PERIODIC_EVT);
- }
- if(events & SBP_PARAM_UPDATE_EVT)
- {
- // Send connect param update request
- GAPRole_PeripheralConnParamUpdateReq(peripheralConnList.connHandle,
- DEFAULT_DESIRED_MIN_CONN_INTERVAL,
- DEFAULT_DESIRED_MAX_CONN_INTERVAL,
- DEFAULT_DESIRED_SLAVE_LATENCY,
- DEFAULT_DESIRED_CONN_TIMEOUT,
- Peripheral_TaskID);
- return (events ^ SBP_PARAM_UPDATE_EVT);
- }
- if(events & SBP_PHY_UPDATE_EVT)
- {
- // start phy update
- PRINT("PHY Update %x...\n", GAPRole_UpdatePHY(peripheralConnList.connHandle, 0,
- GAP_PHY_BIT_LE_2M, GAP_PHY_BIT_LE_2M, GAP_PHY_OPTIONS_NOPRE));
- return (events ^ SBP_PHY_UPDATE_EVT);
- }
- if(events & SBP_READ_RSSI_EVT)
- {
- GAPRole_ReadRssiCmd(peripheralConnList.connHandle);
- tmos_start_task(Peripheral_TaskID, SBP_READ_RSSI_EVT, SBP_READ_RSSI_EVT_PERIOD);
- return (events ^ SBP_READ_RSSI_EVT);
- }
- if(events & TASK_1)
- {
- Get_temp();
- return (events ^ TASK_1);
- }
- if(events & TASK_TEMPRATURE)
- {
- Get_tmprature();
- Temp_Huimt(temprature_buff,t);
- printf("%s\n",t);
- return (events ^ TASK_TEMPRATURE);
- }
- // Discard unknown events
- return 0;
- }
三、功能展示及说明
手机链接蓝牙