使用STM32F1发送和接收LIN,配置的USART2可以正常接收,但是无法发送,这是啥情况啊!!研究2天了
LIN.c
#include "stm32f10x.h"
#include "lin.h"
#include "dsq.h"
#include "LED.h"
int i;
int btl;
u16 temp;
u8 a;
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*配置LED对应位IO口*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE);//复位串口2
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);//停止复位
}
/*******************************************************************************
* Function Name : NVIC_Configuration
* Description : Configures the nested vectored interrupt controller.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //中断分组0
/* enabling interrupt */
NVIC_InitStructure.NVIC_IRQChannel=USART2_IRQn; //配置中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占中断优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从占中断优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中断使能
NVIC_Init(&NVIC_InitStructure); //中断初始化
}
void Uart2_Lin_Configuration(void) //LIN初始化
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate =18000; //波特率19.2千比特
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //传输8位数据
USART_InitStructure.USART_StopBits = USART_StopBits_1; //在帧结尾传输一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //奇偶失能
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制失能
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //发送使能,接收使能
USART_Init(USART2, &USART_InitStructure); //初始化串口2寄存器
USART_LINBreakDetectLengthConfig(USART2,USART_LINBreakDetectLength_11b); //11位中断检测
USART_LINCmd(USART2,ENABLE); //使能LIN模式
USART_Cmd(USART2,ENABLE); //使能串口通信
USART_ITConfig(USART2, USART_IT_RXNE,DISABLE); //串口接收中断关闭
USART_ITConfig(USART2, USART_IT_TXE, DISABLE); //串口发送中断关闭
USART_ITConfig(USART2, USART_IT_LBD, ENABLE); //LIN中断开启
}
void send(u8 dlc,u8 pid,u8 sid) //LIN主机发送程序
{
u8 Crc = 0;
u16 TempData = 0;
USART_ClearITPendingBit(USART2, USART_IT_TXE); //清除发送标志
USART_SendData(USART2,0xFF); //总线高电平
TempData = (dlc&0x03) <<4; TempData |= (pid&0x0f); //标识符校验
Crc = (~(BIT(TempData,1)^BIT(TempData,3)^BIT(TempData,4)^BIT(TempData,5)))<<7;
Crc |= (BIT(TempData,0)^BIT(TempData,1)^BIT(TempData,2)^BIT(TempData,4))<<6;
TempData |= Crc;
USART_SendBreak(USART2); //发送间隔场
USART_SendData(USART2,0x55); //发送同步场
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); //确认发送完成
USART_SendData(USART2,TempData); //发送标识符
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_SendData(USART2,0xe2); //发送数据
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_SendData(USART2,0x0a);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_SendData(USART2,0x00);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_SendData(USART2,0xf5);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
}
void USART2_IRQHandler(void) //USART2中断服务函数
{
if(USART_GetITStatus(USART2, USART_IT_LBD) != RESET) //检测是否收到间隔场
{
USART_ClearITPendingBit(USART2,USART_IT_LBD); //清理中断标志
USART_ITConfig(USART2, USART_IT_LBD, DISABLE); //关闭间隔场中断
chaxun(); //与同步场同步
USART_ITConfig(USART2, USART_IT_RXNE,ENABLE); //开启数据接收中断
}
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //检测是否收到数据
{
a=USART_ReceiveData(USART2); //读取数据
USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清理中断标志位
if(a==0x73)//动作ID,ID等于0x33
{
// USART_SendData(USART2,0x55);
LED1_Turn();
}
if(a==0x43)//反馈ID,ID等于0x03
USART_SendData(USART2,0x55);
}
if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET) //是否发生发送中断
USART_ClearITPendingBit(USART2,USART_IT_TXE); //清理中断标志位
}
void fasong(void) //数据发送程序
{
USART_ITConfig(USART2, USART_IT_RXNE,DISABLE); //关闭数据接收中断
GPIO_SetBits(GPIOB,GPIO_Pin_6);
USART_ITConfig(USART2, USART_IT_TXE, ENABLE); //使能发送中断
USART_ClearITPendingBit(USART2, USART_IT_TXE); //清除发送标志
USART_SendData(USART2,0x0a); //发送数据
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); //确认发送是否完成
USART_SendData(USART2,0x00);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_SendData(USART2,0x13);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_ITConfig(USART2, USART_IT_TXE, DISABLE); //串口发送中断关闭
USART_ITConfig(USART2, USART_IT_LBD, ENABLE); //开启间隔场检测中断
}
void chaxun() //同步场同步程序
{
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10)); //读取IO口
while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
TIM_SetCounter(TIM3, 0); //清0定时器3
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10));
temp=TIM_GetCounter(TIM3); //读取定时器3数值
TIM_SetCounter(TIM3, 0);
TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE );
btl=360000/temp;
btl=btl*8;
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate =btl; //波特率19.2千比特
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //传输8位数据
USART_InitStructure.USART_StopBits = USART_StopBits_1; //在帧结尾传输一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //奇偶失能
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制失能
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //发送使能,接收使能
USART_Init(USART2, &USART_InitStructure); //USART2使能
GPIO_SetBits(GPIOB,GPIO_Pin_6);
}
dsq.c
#include "stm32f10x.h"
#include "dsq.h"
#include "lin.h"
void RCC1_Configuration(void)
{
RCC_DeInit(); //时钟控制器全部设为默认值
RCC_HSICmd(ENABLE); //使能内部高速晶振
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET); //等待内部高速晶振准备就绪
RCC_HCLKConfig(RCC_SYSCLK_Div1); //设置AHB时钟等于系统时钟
RCC_PCLK1Config(RCC_HCLK_Div2); //设置APB1时钟等于HCLK/2时钟
RCC_PCLK2Config(RCC_HCLK_Div1); //设置APB2时钟等于HCLK时钟
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9); //设置PLL为内部系统时钟为36MHZ(8/2*9)
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //等待PLL时钟准备就绪
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //设置PLL时钟为系统时钟源
while(RCC_GetSYSCLKSource() != 0x08); //返回系统所用时钟源确认为内部高速晶振,8M晶振。
/* GPIO for CAN and GPIO for LEDs clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB|
RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA |
RCC_APB2Periph_GPIOC, ENABLE); //使能由APB2时钟控制的外设中的PA,PB,PC和复用IO端口
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
/* CAN1 Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //使能由APB1时钟控制的外设中的USART2端口
//开启SysTick中断
SysTick_Config(36000); //启动
}
void SysTick_Handler(void) //系统滴答定时器中断服务函数
{
nTime--;
}
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
//定时器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断//
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4; //从优先级0级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx
}
//定时器3中断服务程序
void TIM3_IRQHandler(void) //TIM3中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除TIMx更新中断标志
}
}
将发送中断给关掉,发送中断这里使用应该是不正确的!
不知道你这个问题是否已经解决, 如果还没有解决的话:由于你没有提供完整的代码文件,无法确定你的问题出在哪里。但是下面是一些可能导致USART2无法发送LIN数据的常见问题和解决方案。
1.USART2的时钟使能未配置: - 确保你已经在RCC寄存器中使能了USART2的时钟。应该是RCC->APB1ENR |= RCC_APB1ENR_USART2EN; 这段代码。
2.USART2的引脚配置有误: - 确保你已经正确地配置了USART2的引脚。根据你的具体硬件连接,你可能需要将相应的引脚设置为USART2的功能。通常,你可能需要配置GPIO的模式和模式寄存器来设置引脚功能和输出类型。根据你的需求,可能需要选择推挽输出或开漏输出模式,确保引脚与外部设备正确连接。
3.USART2的发送函数未正确调用: - 确保你使用了正确的发送函数来发送LIN数据。通常,你需要调用USART_SendData函数,并将数据写入USART_DR寄存器来发送数据。发送函数的代码可能类似于这样:
void USART2_SendData(uint8_t data) {
while(!(USART2->SR & USART_SR_TXE)); //等待发送寄存器为空
USART2->DR = (data & (uint16_t)0x01FF); //将数据写入发送寄存器
}
请尝试检查以上几个问题,并根据需要进行更正。如果问题仍然存在,请提供更多的代码和错误信息,以便我们更好地帮助你解决问题。