HAL库快速部署I2C
本文主要介绍如何使用STM32CubeMX快速部署串口通信,并与定时器结合进行数据收发的实验。
通信的相关基本概念
串行通信:指设备之间使用少量数据线,一位一位地传输数据的通信方式。
并行通信:指设备之间使用多根数据线,同时进行多位数据传输的通信方式。
单工:指数据只能单向发送或者单向接收的通信方式。
半双工:指数据既可以发送也可以接收,但同一时刻只能发送或者接收。
全双工:指数据在同一时刻既可以发送也可以接收。
同步通信:数据传输过程中会依据时钟信号进行同步,在时钟信号的某个电平或者边沿对数据信号进行采样。
异步通信:数据传输过程中不需要时钟信号,通常在数据信号中加入起始位、停止位、校验位等标识位。
比特率:指每秒传输的二进制位数。
波特率:指每秒传输的码元数量,码元个人的理解就是另一种表示信息的形式,我们将固定时间间隔内的二进制信息划分为一个码元,比如00、01、11、10,分别表示1、2、3、4,这样把信号视为用码元表示了。一个码元所含比特数=log2(码元进制数)
串口通信基本知识
串口通信是一种串行通信方式,物理层现在基本由TXD、RXD和GND三条信号线组成,协议层包括起始位、主体数据、校验位以及停止位。
起始位和停止位:数据包的起始信号由一个逻辑 0 的数据位表示,而数据包的停止信号可由 0.5、1、1.5 或 2 个逻辑 1 的数据位表示,只要双方约定一致即可。
主体数据:通常约定为5、6、7、8位长。
校验位:在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验 (odd)、偶校验(even)、0 校验 (space)、1 校验 (mark) 以及无校验 (noparity)。
定时器与串口的综合应用
一、实验目的
实现如下效果:
1.单片机上电后绿灯亮,0.5s后熄灭,标志系统开启;
2.系统向上位机发送“stm32欢迎您!”;
3.系统蓝灯开始以0.5s闪烁,并开始记录时间,时间格式为“XX:XX:XX”;
4.上位机可以通过格式为“0XBF 控制字 0XFB”格式的命令帧控制计时的开启和暂停。控制字为0XA1为暂停,发送“计时暂停”,蓝灯停止闪烁;0XA2为开始,蓝灯再次闪烁,发送“计时恢复”;发送其他控制字,亮红灯,发送“指令错误”。
二、cubemx配置
1.新建工程,常规配置调试模式、时钟树、项目环境;
2.选择PB0、PB1、PB5配置为GPIO_Out,初始为高电平;
3.选择USART1,配置为异步通信,选择好波特率、数据包长度、校验位、停止位、单工还是全双工,需要使用中断时还要在NVIC设置中使能中断。
4.选择TIM2,配置时钟源、预分频系数、自动重装载计数、使能定时器中断
5.GENERATE CODE
三、代码编写
1.宏定义和全局变量
(1)封装点灯函数
#define LEDR_ON HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET)
#define LEDG_ON HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET)
#define LEDB_ON HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET)
#define LEDR_OFF HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET)
#define LEDG_OFF HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET)
#define LEDB_OFF HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET)
#define LEDB_TRIGGER HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1)
(2)全局变量
uint8_t welc[] = {"welcome to STM32!\r\n"};
uint8_t timp[] = {"Time pause\r\n"};
uint8_t timr[] = {"Time restore\r\n"};
uint8_t errs[] = {"wrong command\r\n"};
uint8_t hh = 0; //小时
uint8_t mm = 0; //分钟
uint8_t ss = 0; //秒钟
uint8_t ssh = 0; //定时0.5秒
uint8_t timbuf[16]; //存放处理过时间的数组
uint8_t revbuf[3]; //指令接收数组
2.程序主体
(1)主函数
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_TIM2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
LEDG_ON;
HAL_UART_Transmit(&huart1,welc,sizeof(welc),10000);
HAL_Delay(500);
HAL_TIM_Base_Start_IT(&htim2); //开时钟
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
HAL_UART_Receive_IT(&huart1,revbuf,sizeof(revbuf));
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
(2)串口接收回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == &huart1)
{
if((revbuf[0] == 0xBF)&&(revbuf[2] == 0xFB))
{
if(revbuf[1] == 0xA0)
{
HAL_TIM_Base_Stop(&htim2); //关时钟
LEDR_OFF;
LEDB_ON;
HAL_UART_Transmit(&huart1,timp,sizeof(timp),10000);
sprintf((char *)timbuf,"%02d:%02d:%02d\n",hh,mm,ss);
HAL_UART_Transmit(&huart1,timbuf,sizeof(timbuf),10000);
}
else if(revbuf[1] == 0xA1)
{
HAL_TIM_Base_Start_IT(&htim2);
HAL_UART_Transmit(&huart1,timr,sizeof(timr),10000);
sprintf((char *)timbuf,"%02d:%02d:%02d\n",hh,mm,ss);
HAL_UART_Transmit(&huart1,timbuf,sizeof(timbuf),10000);
}
else
{
HAL_TIM_Base_Stop(&htim2);
LEDB_OFF;
LEDR_ON;
HAL_UART_Transmit(&huart1,errs,sizeof(errs),10000);
sprintf((char *)timbuf,"%02d:%02d:%02d\n",hh,mm,ss);
HAL_UART_Transmit(&huart1,timbuf,sizeof(timbuf),10000);
}
}
else
{
HAL_TIM_Base_Stop(&htim2);
LEDB_OFF;
LEDR_ON;
HAL_UART_Transmit(&huart1,errs,sizeof(errs),10000);
sprintf((char *)timbuf,"%02d:%02d:%02d\n",hh,mm,ss);
HAL_UART_Transmit(&huart1,timbuf,sizeof(timbuf),10000);
}
}
}
(3)定时器回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim2)
{
LEDG_OFF;
LEDB_TRIGGER;
/***时间处理**/
ssh++;
if(ssh == 2)
{
ss++;
ssh =0;
}
if(ss == 60)
{
mm++;
ss = 0;
}
if(mm == 60)
{
hh++;
mm = 0;
}
}
}