回声函数 printf重定向 sht20温湿度传感器
HAL_UART_Receive(&huart1, data1, 1, 20);
/*
&huart1:这是一个指向UART句柄的指针,huart1是预先定义好的UART句柄,用于标识特定的UART接口。
data1:这是一个数组,用于存储从UART接口接收到的数据。
10:这是要接收的数据字节数。
2000:这是超时时间,单位是毫秒。如果在2000毫秒内没有接收到足够的数据,函数将返回一个超时错误。
*/
if(data1[0])
{
if(data1[0]==0x30)
{
HAL_GPIO_WritePin(Status_GPIO_Port,Status_Pin,0);
}
else if(data1[0]==0x31)
{
HAL_GPIO_WritePin(Status_GPIO_Port,Status_Pin,1);
}
HAL_UART_Transmit(&huart1, data1, 1, 20);
data1[0]=0;
}
printf的重定向
把printf链接到串口上,可以通过 串口调试助手查看打印的值
Printf重定向-CSDN博客
在STM32微控制器中,USART_ISR的TC位(Transmission Complete)是一个非常重要的标志位,它表示USART的发送操作已经完成。具体来说,TC位在USART的数据寄存器(DR)发送完最后一个位时被硬件置位。这意味着,当USART的数据寄存器中的数据被完全发送出去,并且移位寄存器也为空时,TC位会被设置。
TC位的使用通常与中断服务相关。当TC位被设置时,如果相应的中断使能位(TCIE)被设置,那么会产生一个中断请求,允许微控制器的中断服务程序(ISR)处理发送完成的事件。在中断服务程序中,通常需要清除TC位以避免重复进入中断,这可以通过读取USART_SR寄存器和写入USART_DR寄存器来完成,或者使用库函数USART_ClearFlag(USART1, USART_FLAG_TC)来清除。
总结来说,USART_ISR的TC位是一个指示发送操作完成的标志位,它在数据完全发送完毕后被硬件置位,并可用于触发中断,以便软件可以执行后续操作,如发送下一个字节或者关闭发送器。
#if 1
#include <stdio.h>
int fputc(int ch, FILE *stream)
{
/* 堵塞判断串口是否发送完成 */
while((USART1->ISR & 0X40) == 0);//当 USART1->ISR 的TC 位为1
/* 串口发送完成,将该字符发送 */
USART1->TDR = (uint8_t) ch;
return ch;
}
#endif
/* USER CODE BEGIN 3 */
HAL_UART_Receive(&huart1, data1, 1, 20);
/*
&huart1:这是一个指向UART句柄的指针,huart1是预先定义好的UART句柄,用于标识特定的UART接口。
data1:这是一个数组,用于存储从UART接口接收到的数据。
10:这是要接收的数据字节数。
2000:这是超时时间,单位是毫秒。如果在2000毫秒内没有接收到足够的数据,函数将返回一个超时错误。
*/
if(data1[0])
{
if(data1[0]==0x30)
{
HAL_GPIO_WritePin(Status_GPIO_Port,Status_Pin,0);
}
else if(data1[0]==0x31)
{
HAL_GPIO_WritePin(Status_GPIO_Port,Status_Pin,1);
}
printf("data1[0]:=%x\n",data1[0]);
data1[0]=0;
}
}
/* USER CODE END 3 */
用到了C库,所以此处勾选下C库
自己写个重定向函数:
回声函数结合温湿度传感器
SHT20温度传感器
I2C协议之SHT20传感器采样温湿度-CSDN博客
PB7——I2C1_SDA1
PB6——I2C1_SCL
SHT20 温湿度传感器是一种数字式温湿度传感器,它采用超薄膜式湿度传感器和热敏电阻式温度传感器,在测量环境温度和湿度方面具有高精度和可靠性。
SHT20 传感器使用 I2C 总线接口进行数据通信,它能够快速、准确地测量环境的温度和相对湿度。
I2C设备地址
1. I2C总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。
2. 主机在起始信号后必须传送一个从机的地址(7位),第8位是数据的传送方向位(R/W),用“0”表示主机发送数据(W),“1”表示主机接收数据(R)。
3. 总线上的每个从机都将这7位地址码与自己的地址进行比较,如果相同,则认为自己被主机寻址,根据R/W位将自己定为发送器或接收器。
I2C(Inter-Integrated Circuit)设备地址是用于在I2C总线上唯一标识每个设备的地址。I2C协议允许多个设备共享同一总线,因此每个设备都必须有一个唯一的地址,以便主设备可以准确地与它们通信。以下是关于I2C设备地址的一些关键点:
1. 地址长度:I2C地址通常为7位或10位。7位地址是最常用的,它允许多达127个不同的设备地址(从0x00到0x7F)。10位地址提供了更多的地址空间,但不是所有的I2C主设备都支持10位寻址。
2. 地址分配:设备地址由设备制造商在生产时设定,通常是一个固定的值,可以在设备的数据手册中找到。有些设备可能允许通过特定的引脚配置来改变地址,以避免地址冲突。
3. 读写操作:在I2C通信中,地址后面通常跟着一个读/写位(R/W位)。这个位指示随后的数据传输是读操作(R/W位为1)还是写操作(R/W位为0)。例如,如果设备地址是0x50,那么写操作的起始条件可能是0x50+0(写),读操作的起始条件可能是0x50+1(读)。
4. 地址广播:I2C地址也可以用于广播消息,这通常涉及到使用特殊的广播地址,允许所有设备接收消息,但只有特定的设备会根据消息内容做出响应。
7. 地址识别:在I2C总线上,主设备通过发送设备的地址来启动通信。从设备在检测到自己的地址并看到R/W位后,会发送一个应答信号(ACK),表示它已经准备好进行通信。
5. 地址冲突:如果两个设备有相同的地址,它们将无法在同一I2C总线上正常工作,因为主设备无法区分它们。因此,确保地址唯一性是非常重要的。
6. 地址扩展:一些I2C设备具有地址扩展功能,允许通过额外的引脚来设置地址的高位,从而提供更多的地址组合。
手册分析
设备地址:1000 000
命令
任务实现
CubeMX
数据转换
通信时序软件iic
起始与终止
起始条件:SCL高电平期间,SDA从高电平切换到低电平
终止条件:SCL高电平期间,SDA从低电平切换到高电平
数据传输
发送一个字节
SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节。
接收一个字节
SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)
应答信号
发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答
接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)
#define sht20_address_write 0x80
#define sht20_address_read 0x81
#define t_cmd 0xe3 // 温度
#define rh_cmd 0xe5 // 湿度
uint8_t buf[2] = {0};
uint16_t val = 0;
// 读数据
uint16_t sht20_read(uint8_t cmd){
HAL_I2C_Master_Transmit(&hi2c1,sht20_address_write,&cmd,1,100);
HAL_I2C_Master_Receive(&hi2c1,sht20_address_read,buf,2,100);
val = (buf[0]<<8) | buf[1]; // 把两个8位数据组合成一个16位的数据
return val; // 把16位数据return出来
}
// 处理数据并显示出来
void sht20_data(){
uint16_t t_num = 0,rh_num = 0,t_tempnum = 0,rh_tempnum = 0;
t_tempnum = sht20_read(t_cmd);
rh_tempnum = sht20_read(rh_cmd);
rh_num = -6+125*t_tempnum/65536;
t_num = -46.85 + 175.72*t_tempnum/65536;
printf("温度:%d,湿度:%d\n",t_num,rh_num);
}
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_UART_Receive(&huart1, data, 1, 20);
sht20_data();
if(data[0])
{
if(data[0]==0x30)
{
HAL_GPIO_WritePin(Status_GPIO_Port,Status_Pin,0);
}
else if(data[0]==0x31)
{
HAL_GPIO_WritePin(Status_GPIO_Port,Status_Pin,1);
}
//HAL_UART_Transmit(&huart1, data, 1, 20);
printf("data1[0]:=%x\n",data[0]);
data[0]=0;
}
//HAL_UART_Receive(&huart1, data, 10, 2000);
//HAL_UART_Transmit(&huart1, data, 10, 200);
//HAL_Delay(1000);
//HAL_GPIO_TogglePin(Status_GPIO_Port,Status_Pin);
}
/* USER CODE END 3 */
输出: