不知道是不是因为我的方法不合理,使用了while()循环来485发送帧数据的时候,数码管会闪烁,普通串口不会,不知道问题是不是在while()这里。
//485收发上图:
贴代码(stm32f103ret6):
//main.c
#include "stm32f10x.h" // Device header
#include "LED.H"
#include "DISPLAY.H"
#include "TIMER.H"
#include "USART.H"
#include "RS485.H"
int main(void)
{
LED_Init();
DISPLAY1_Init();
KEY_Init();
INTERRUPT_Init();
Timer_Init();
USART1_Init();
RS485_Init();
while (1)
{
}
}
//rs485.h
#ifndef __RS485_H
#define __RS485_H
void RS485_Init(void);
extern unsigned int Uart4_Rx;
extern unsigned char Uart4_Buffer[ ];
extern uint16_t Uart4_Tx_Num;
#endif
//rs485.c
#include "stm32f10x.h" // Device header
#include "DISPLAY.H"
//RS485(UART4) : TX/PC10; RX/PC11; DE/PA12。
void RS485_Init(void)
{
//GPIO_配置UART4_DE(PA12);并初始化为低电平,UART4_485为接收模式。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启对应GPIO_时钟
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO_结构体
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, GPIO_Pin_12); //初始化UART4_DE为低电平,UART4_485默认为接收模式。
//GPIO_配置UART4_TX(PC10)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //开启对应GPIO_时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//GPIO_配置UART4_RX(PC11)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//USART_配置UART4(波特率9600,长度8字节,1停止位,0奇偶校验位,0硬件流控制)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE); //开启对应USART_时钟
USART_InitTypeDef USART_InitStructure; //定义USART_结构体
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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(UART4, &USART_InitStructure);
USART_ITConfig(UART4, USART_IT_RXNE, ENABLE); //接收中断,使能
USART_ITConfig(UART4, USART_IT_IDLE, ENABLE); //空闲总线中断,使能
USART_Cmd(UART4, ENABLE); //使设定的配置生效,但在STM32里,需要配合对应的时钟使用
//NVIC_配置UART4(优先级分组2,抢占优先级为1,响应优先级为1)
NVIC_InitTypeDef NVIC_InitStructure; //定义NVIC_结构体
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
#define Max_BUFF_Len_4 18
unsigned char Uart4_Buffer[ Max_BUFF_Len_4 ];
unsigned int Uart4_Rx = 0;
void UART4_ReceiveData(void)
{
if(USART_GetITStatus (UART4,USART_IT_RXNE)) //接收中断
{
Uart4_Buffer[ Uart4_Rx ] = USART_ReceiveData(UART4);
Uart4_Rx ++;
if(Uart4_Rx >=201) //防止达数组上限
{
Uart4_Rx = 0;
}
}
}
uint16_t Uart4_Tx_Num =0;
void UART4_TX(void)
{
static uint32_t Clear;
if(USART_GetITStatus (UART4,USART_IT_IDLE)) //总线空闲中断
{
while(Uart4_Rx >=1) //485循环发送数组Uart4_Buffer[ ]内的数,解决只一次发送的问题
{
GPIO_SetBits(GPIOA, GPIO_Pin_12); //485发送使能
USART_SendData(UART4,Uart4_Buffer[ Uart4_Tx_Num ]);
Uart4_Tx_Num ++; //485发送顺序从数组Uart4_Buffer[ 0-100 ]
while(USART_GetFlagStatus (UART4,USART_FLAG_TC) !=1);
if(Uart4_Tx_Num == Uart4_Rx ) // 待发送完成
{
Uart4_Rx = 0;
Uart4_Tx_Num = 0;
}
}
if(Uart4_Rx ==0)
{
Clear = UART4->SR; //跳出总线空闲中断
Clear = UART4->DR; //跳出总线空闲中断
GPIO_ResetBits(GPIOA, GPIO_Pin_12);
}
}
}
void UART4_IRQHandler(void)
{
UART4_ReceiveData();
UART4_TX();
USART_ClearFlag (UART4,USART_FLAG_TC);
}
//usart.h
#ifndef __USART_H
#define __USART_H
void USART1_Init(void);
extern unsigned int Usart1_Rx;
extern unsigned char Usart1_Buffer[ ];
#endif
//usart.c
#include "stm32f10x.h"
//USART1 : TX/PA9; RX/PA10。
void USART1_Init(void)
{
//GPIO_配置USART1_TX(PA9)
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA ,ENABLE ); //GPIOA时钟开启
GPIO_InitTypeDef GPIO_InitInstructure;
GPIO_InitInstructure.GPIO_Mode = GPIO_Mode_AF_PP; //选择引脚模式,TX 需配置为:_AF_PP(复用推挽输出,用作串口的输出)
GPIO_InitInstructure.GPIO_Pin = GPIO_Pin_9; //选择引脚
GPIO_InitInstructure.GPIO_Speed = GPIO_Speed_50MHz; //选择引脚频率
GPIO_Init(GPIOA,&GPIO_InitInstructure ); //进行参数初始化
//GPIO_配置USART1_RX(PA10)
GPIO_InitInstructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //选择引脚模式,RX 需配置为:_IN_FLOATING(浮空输入,由于其输入阻抗比较大,一般把这种模式用于标准的通讯协议,比如IIC、USART等)
GPIO_InitInstructure.GPIO_Pin = GPIO_Pin_10; //选择引脚
GPIO_InitInstructure.GPIO_Speed = GPIO_Speed_50MHz; //RX引脚,也可以不配置引脚频率
GPIO_Init(GPIOA,&GPIO_InitInstructure ); //进行参数初始化
//USART_配置USART1(波特率9600,长度8字节,1停止位,0奇偶校验位,0硬件流控制)
RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1 ,ENABLE ); //串口USART1时钟开启
USART_InitTypeDef USART_InitInstructure;
USART_InitInstructure.USART_BaudRate = 9600; //直接修改波特率即可
USART_InitInstructure.USART_WordLength = USART_WordLength_8b; //长度 8字节
USART_InitInstructure.USART_StopBits = USART_StopBits_1; //1位 停止位
USART_InitInstructure.USART_Parity = USART_Parity_No; //无 奇偶校验位
USART_InitInstructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无 硬件流控制
USART_InitInstructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //使能发送与接收功能
USART_Init(USART1,&USART_InitInstructure);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //接收中断,使能
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE); //总线空闲中断,使能
USART_Cmd (USART1 ,ENABLE ); //使设定的配置生效,但在STM32里,需要配合对应的时钟使用
//NVIC_配置USART1(优先级分组2,抢占优先级为2,响应优先级为2)
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //从stm32f10x.h里第243-268行选择
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级为2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //响应优先级为2
NVIC_Init(&NVIC_InitStructure); //进行参数初始化
}
#define Max_BUFF_Len_1 18
unsigned char Usart1_Buffer[ Max_BUFF_Len_1 ];
unsigned int Usart1_Rx = 0;
void USART1_IRQHandler(void)
{
if(USART_GetITStatus (USART1,USART_IT_RXNE)) //接收中断
{
Usart1_Buffer[ Usart1_Rx ] = USART_ReceiveData(USART1);
Usart1_Rx ++;
USART_SendData(USART1,Usart1_Buffer[ Usart1_Rx -1 ]); //接收完立即发
Usart1_Rx = 0;
}
USART_ClearFlag (USART1,USART_FLAG_TC);
}
//TIMER.H
#ifndef __TIMER_H
#define __TIMER_H
void Timer_Init(void);
void TIM2_IRQHandler(void);
extern uint16_t k;
#endif
//TIMER.c
#include "stm32f10x.h" // Device header
#include "DISPLAY.H"
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //开启TIM2时钟
TIM_InternalClockConfig(TIM2); //
//计数器溢出频率CK_CNT_OV = CK_CNT / (ARR + 1)= CK_PSC / (PSC + 1) / (ARR + 1)
//内部时钟默认为72M,此处选用内部时钟频率的话
//若设置为72M/(7200-1 +1) /(10000-1 +1) = 1秒,即:1秒进中断一次。
//结构体(TIM_TimeBaseInitStructure),在本函数内定义一次即可
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //滤波采样分频系数,1/2/4分频。它影响的是滤波器的采样(输入)频率,与输出无关
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; //定时器预分频器设置,可设置范围为 0 至 65535,实现 1 至 65536 分频,内部自动+1。
TIM_TimeBaseInitStructure.TIM_Period = 10 - 1; //定时器周期,设定自动重载寄存器的值,在事件生成时更新到影子寄存器。可设置范围为 0 至 65535,内部自动+1。
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //高级定时器才有的。周期倍数:n+1倍。此处为0时,即1倍周期1s;为1时即2倍周期2s,n最大为225(0XFF)。
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //初始化参数(TIM)
TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除更新中断,避免一打开中断就立刻产生中断
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //打开定时器更新中断
//前提条件1:组别优先顺序(第0组优先级最强,第4组优先级最弱):NVIC_PriorityGroup_0>NVIC_PriorityGroup_1>NVIC_PriorityGroup_2>NVIC_PriorityGroup_3>NVIC_PriorityGroup_4
//前提条件2:不同组优先级别间,依据优先级强弱,优先级别高的组,其中断源可以打断优先级别低的组的正在做的事情;(即:不同组优先级间,可以中断嵌套)
//前提条件3:组优先级别>抢占优先级别>响应优先级别
//前提条件4:抢占优先级越小,优先级越高;但同组优先级不能相互打断,也就没有中断嵌套
//前提条件5:响应优先级越小的中断首先执行(不能嵌套),如果响应优先级也均相同,则根据各中断对应向量表的位置来确定,向量表中越靠前的中断先响应
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //函数优先级分组配置,共5组(0-4),此处为第1组。
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //选择EXTI2中断 ,对应之前开启的TIM2时钟
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能EXTI2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //响应优先级
NVIC_Init(&NVIC_InitStructure); //初始化参数(NVIC)
TIM_Cmd(TIM2, ENABLE); //使能TIM2外设
}
uint16_t k = 1;
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) //检查指定的TIM中断发生与否
{
k ++;
if(k >= 40)
{
k = 1;
}
Display();
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除TIM2的中断待处理位
}
}
//display.h
#ifndef __DISPLAY_H
#define __DISPLAY_H
void DISPLAY1_Init(void);
void Display(void);
extern uint16_t n;
extern uint16_t p;
#endif
//display.c
#include "stm32f10x.h" // Device header
#include "TIMER.H"
#include "USART.H"
#include "RS485.H"
void DISPLAY1_Init(void) //初始化时可以设置为默认完全打开功能,检测硬件是否OK
{
//PB4:SGE1(位选1);PB3:SEG2(位选2)
//PC13:a;PC14:b;PC15:c;PC1:d;
//PC3:e;PA2:f;PA3:g;PC0:dp。
//GPIO_Write(GPIOC, 0xE00B);
//GPIO_Write(GPIOA,0x000C);
//共阴数码管:所有阴极(负极)连在(并在)一起。共阳同理。
//结构体:
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体GPIO_InitStructure,用它来传递数据
//STM32F10x系列的MCU复位后,PA13/14/15 & PB3/4默认配置为JTAG功能。有时我们为了充分利用MCU I/O口的资源,会把这些端口设置为普通I/O口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //使能相应GPIOB端口时钟以及AFIO功能时钟(复用时钟),在使用时开启,一方面可以降低功耗;
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
//枚举类型:规范、限制变量赋值、取值范围,使其不能随意取值。
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //选择引脚模式,结构体GPIO_InitStructure内枚举类型GPIO_Mode赋值
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4 ; //选择引脚,结构体GPIO_InitStructure内枚举类型GPIO_Pin赋值
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //选择引脚频率,结构体GPIO_InitStructure内枚举类型GPIO_Speed赋值
GPIO_Init(GPIOB,&GPIO_InitStructure); //进行参数初始化(GPIOB), &:取地址符号,这里使用地址传递
// GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4); //赋值,数码管高电平有效,非初始化必需步骤
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC ,ENABLE );
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
GPIO_InitStructure .GPIO_Pin =GPIO_Pin_15|GPIO_Pin_14|GPIO_Pin_13|GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz ;
GPIO_Init (GPIOC,&GPIO_InitStructure );
// GPIO_SetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_3|GPIO_Pin_15|GPIO_Pin_14|GPIO_Pin_13); //高电平有效
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA,ENABLE );
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_2|GPIO_Pin_3 ;
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
// GPIO_SetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3);
}
uint16_t p;
uint16_t n;
//通过定时器内k(1-40)的自增循环,来进行数码管的点亮刷新
void Display(void)
{
if(k >= 1 && k <= 19 )
{
GPIO_Write(GPIOB, 0x0010 ); //数码管位选1
}
if(k >= 20 && k <= 39)
{
GPIO_Write(GPIOB, 0x0008 ); //数码管位选2
}
//0-9
const uint16_t num_table_1[] = {0xE00A,0xC000,0x600A,0xE002,0xC000,0xA002,0xA00A,0xE000,0xE00A,0xE002}; //,0x0001
const uint16_t num_table_2[] = {0x0004,0x0000,0x0008,0x0008,0x000C,0x000C,0x000C,0x0000,0x000C,0x000C}; //,0x0000
p= 1;//Uart4_Rx / 10 %10 ;
n= 2;//Uart4_Rx % 10;
if(GPIO_ReadInputDataBit (GPIOB ,GPIO_Pin_4) == 1)
{
GPIO_Write(GPIOC, num_table_1[p] );
GPIO_Write(GPIOA, num_table_2[p] );
}
if(GPIO_ReadInputDataBit (GPIOB ,GPIO_Pin_3) == 1)
{
GPIO_Write(GPIOC, num_table_1[n] );
GPIO_Write(GPIOA, num_table_2[n] );
}
}
|