stm32f103 配置UART_DMA通信 CAN通信
时钟配置
uart1引脚配置
加入dma
配置中断
生成后 函数stm32f1xx.it.c配置
这是在中断中判定是否有uart_dma接收 记得定义成局变量
void USART1_IRQHandler(void)
{
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET) //串口1空闲中断
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位
//temp = huart1.Instance->SR; //清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能
//temp = huart1.Instance->DR; //读取数据寄存器中的数据
HAL_UART_DMAStop(&huart1);
rx_len = 100 - __HAL_DMA_GET_COUNTER(huart1.hdmarx); // 获取DMA中未传输的数据个数
//__HAL_DMA_GET_COUNTER(huart1.hdmarx) = hdma_usart1_rx.Instance->NDTR;//读取NDTR寄存器 获取DMA中未传输的数据个数,
uart_flag = 1;
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
配置主函数
HAL_UART_Receive_DMA(&huart1,uart_rx,100);是开启中断,每运行一次开启一次
//UART
uint8_t rx_len;
uint8_t uart_rx[200];
uint8_t uart_flag = 0;
//CAN
uint8_t can_rx[200];
int main(void)
{
HAL_Init();
SystemClock_Config();
//初始化外设
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
can_start_init();
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)"DMA IS OK\r\n", strlen("DMA IS OK\r\n"));
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能IDLE中断
HAL_UART_Receive_DMA(&huart1,uart_rx,100);//DMA接收函数
while (1)
{
if(uart_flag)
{
uart_proc();
}
}
/* USER CODE END 3 */
}
void uart_proc(void)
{
HAL_UART_Transmit_DMA(&huart1, uart_rx, rx_len);//发送到上位机
//内容清除
rx_len = 0;
memset(uart_rx,0,rx_len);
uart_flag = 0;
HAL_UART_Receive_DMA(&huart1,uart_rx,100);//再次开启中断
}
试验成功
配置can
can挂载在APB1上 频率36MHZ 36M/(prs * (seg1 + seg2 + rjw)) = 500 Kbps
can引脚
开启中断
can有四种通信模式
双机通信 NORMAL实现局域网通信
回环模式 LOOPBACK只有一块板子时的代码调试
两种模式代码一样,只需要改变模式
void MX_CAN_Init(void)
{
hcan.Instance = CAN1;
hcan.Init.Prescaler = 8;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_2TQ;
hcan.Init.TimeSeg2 = CAN_BS2_6TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = DISABLE;
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = DISABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
}
can.c代码封装 还有filter需要配置
void CAN_Filter_Config(void)
{
CAN_FilterTypeDef CAN_FilterInit;
CAN_FilterInit.FilterBank = 0;
CAN_FilterInit.FilterMode = CAN_FILTERMODE_IDMASK;
CAN_FilterInit.FilterScale = CAN_FILTERSCALE_32BIT;
CAN_FilterInit.FilterIdHigh = 0X0000;
CAN_FilterInit.FilterIdLow = 0X0000;
CAN_FilterInit.FilterMaskIdHigh = 0X0000;
CAN_FilterInit.FilterMaskIdLow = 0X0000;
CAN_FilterInit.FilterFIFOAssignment = CAN_FILTER_FIFO0;
CAN_FilterInit.FilterActivation = ENABLE;
HAL_CAN_ConfigFilter(&hcan1, &CAN_FilterInit);
}
void CAN_Send(uint8_t *data)
{
uint32_t pTxmailbox;
TxHeader.StdId = 0x09;
TxHeader.ExtId = 0x00;
TxHeader.IDE = CAN_ID_STD;
TxHeader.DLC = 8;
TxHeader.RTR = CAN_RTR_DATA;
while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) == 0); //等待有空发送邮箱
HAL_CAN_AddTxMessage(&hcan1, &TxHeader, data, &pTxmailbox);
}
void MX_CAN_START_Init(void)
{
MX_CAN_Init();//can初始化
CAN_Filter_Config();//过滤器初始化
HAL_CAN_Start(&hcan1); //can1传输使能
HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);//使能中断
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if(hcan->Instance == CAN1)
{
if(HAL_CAN_GetRxMessage(&hcan1, CAN_FILTER_FIFO0, &RxHeader, can_rx) == HAL_OK)//获取数据
{
// HAL_UART_Transmit_DMA(&huart1, (uint8_t *)"CAN IS OK\r\n", strlen("CAN IS OK\r\n"));
int i;
for(i = 0; i < 4; i++)
{
can_infor[i] = can_rx[i];
can_tx[i] = 0;
can_rx[i] = 0;
}
HAL_UART_Transmit_DMA(&huart1, can_infor, 4);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);//使能中断
}
}
}
对串口进行改动,上位机串口每次发送数据都通过can发送到另一块板子
注意can最大发送字符数为8
void uart_proc(void)
{
int i;
for(i = 0; i < 4; i++)
{
can_tx[i] = uart_rx[i];
uart_rx[i] = 0;
}
CAN_Send(can_tx);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);
HAL_Delay(20);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);
HAL_Delay(20);
// HAL_UART_Transmit_DMA(&huart1, can_tx, uart_rx_len);//发送到上位机
// memset(uart_rx,0,uart_rx_len);
// uart_rx_len = 0;
uart_flag = 0;
HAL_UART_Receive_DMA(&huart1, uart_rx, 100);//再次开启中断
}
实验结果
回环模式
双机通信