串⼝配置使⽤的⼀般步骤及实例解读串⼝配置的⼀般步骤
1. 串⼝时钟使能,GPIO时钟使能:RCC_APB2PeriphClockCmd();
2. 串⼝复位:USART_DeInit(); 这⼀步不是必须的
3. GPIO端⼝模式设置:GPIO_Init(); 模式设置为GPIO_Mode_AF_PP
4. 串⼝参数初始化:USART_Init();
5. 开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)
NVIC_Init();
USART_ITConfig();
6. 使能串⼝:USART_Cmd();
7. 编写中断处理函数:USARTx_IRQHandler();
8. 串⼝数据收发:
void USART_SendData(); //发送数据到串⼝,DR
uint16_t USART_ReceiveData(); //接受数据,从DR读取接受到的数据
9. 串⼝传输状态获取:
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
注:使⽤中断需要操作5、7、8步骤,否则不需要。
部分官⽅库函数的解读在该博客内有说明
串⼝整体初始化函数(⾮库函数/整合上述步骤1-6)
#define USART_WordLength_8b ((uint16_t)0x0000)
#define USART_StopBits_1 ((uint16_t)0x0000)
#define USART_Parity_No ((uint16_t)0x0000)
#define USART_HardwareFlowControl_None ((uint16_t)0x0000)
#define USART_Mode_Rx ((uint16_t)0x0004)
#define USART_Mode_Tx ((uint16_t)0x0008)
离婚需要什么手续void uart_init(u32 bound) //串⼝整体初始化函数
{
//各种结构体声明
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//使能USART1,GPIO时钟对应上述步骤1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
/
/初始化USART1_TX端⼝对应的GPIOA9 对应上述步骤3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //设置GPIO端⼝号为PA9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置传输速度为50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //输出模式为复⽤推挽输出
神童女友GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA9
//初始化USART1_RX端⼝对应的GPIOA10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //设置GPIO端⼝号为PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //输⼊模式为浮空输⼊
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA10
//串⼝初始化设置对应上述步骤4
USART_InitStructure.USART_BaudRate = bound; //设置串⼝的波特率为函数的⼊⼝参数
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(USART1, &USART_InitStructure); //初始化串⼝1,该函数的部分内容在上⼀篇
//串⼝中断设置对应上述步骤5
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //选定串⼝1的中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; //抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //⼦优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串⼝接收中断
//使能串⼝1 对应上述步骤6
USART_Cmd(USART1, ENABLE); //该函数在上⽂已说明叶童三级
}
串⼝中断服务函数
//头⽂件的定义
#define USART_REC_LEN 200 //定义最⼤接收字节数为200
#define EN_USART1_RX 1 //使能(1)/禁⽌(0)串⼝1接收
extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最⼤USART_REC_LEN个字节,末尾为换⾏符extern u16 USART_RX_STA; //接收状态标记
苗苗身高void uart_init(u32 bound);
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; //枚举变量
#define USART_IT_RXNE ((uint16_t)0x0525) //10100100101
//源⽂件的定义
#if EN_USART1_RX //如果使能了接收
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最⼤USART_REC_LEN个字节
u16 USART_RX_STA=0; //接收状态标记 bit15 接收完成标志,接收完成后为1;
接上⼀⾏bit14 接收到0x0d后为1;bit13-bit0 为接收到的有效字节数
//串⼝中断服务函数对应上述步骤7
void USART1_IRQHandler(void)
{
u8 Res;
/
/接收中断(接收到的数据必须是0x0d 0x0a结尾)
//获取串⼝1的当前状态,如果不等于0,则满⾜条件
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
Res =USART_ReceiveData(USART1); //读取接收到的数据(按字节接收)
//接收状态标记(初始为0)和0x8000进⾏与运算,若位15不为0,则满⾜条件
if((USART_RX_STA&0x8000)==0) //正在接收(未完成接收)
{
//接收状态标记变量和0x4000进⾏与运算,若位14不为0,则满⾜条件
if(USART_RX_STA&0x4000) //上⼀次接收已经接收到了0x0d
{
/
/如果当前接收到的字节不是0x0a,则接收错误,接收状态标记清零
if(Res!=0x0a)USART_RX_STA=0; //接收错误,重新开始
//如果当前字节是0x0a,则设置USART_RX_STA变量的位15为1
else USART_RX_STA|=0x8000; //接收完成
}
else //上⼀次接收还没有收到0x0d
{
//如果该次接收收到了0x0d,设置接收状态标记的位14为1
if(Res==0x0d)USART_RX_STA|=0x4000;
else //该次接收还没收到0x0d
{
/
/USART_RX_BUF数组的第位为接收的字符(存⼊缓冲区)
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++; //接收次数⾃增(字符数+1)
//如果接收的字符数超过最⼤字符数-1个
if(USART_RX_STA>(USART_REC_LEN-1))
{
USART_RX_STA=0; //接收数据错误,重新开始接收
}
}
}
}
}
}
串⼝收发函数(上述函数的应⽤主函数)
int main(void) //串⼝收发函数对应上述步骤8
{
u8 t; u8 len; u16 times=0;
//初始化延时、中断、串⼝、LED
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组
化生寺怎么加点uart_init(9600); //串⼝初始化为9600
LED_Init(); //初始化与LED连接的硬件接⼝
while(1)
{
//接收状态标记变量和0x8000进⾏与运算,若位15为1(接收完成)则进⼊ if(USART_RX_STA&0x8000)
{
//接收状态标记变量与0x3fff进⾏与运算,获取位13-0存储的数据长度
len=USART_RX_STA&0x3fff;
printf("\r\n您发送的消息为:\r\n"); //打印到串⼝
for(t=0;t<len;t++)
{
//将DR=USART_RX_BUF中存储的数据按位传输给DR寄存器
USART1->DR=USART_RX_BUF[t];
//等待SR寄存器的位6为1时(发送完成时),跳出循环
while((USART1->SR&0X40)==0); //等待发送结束
}
printf("\r\n\r\n"); //插⼊换⾏
USART_RX_STA=0; //清空接收状态标记变量
}
else //接收未完成
{
times++; //时间⾃增
if(times%5000==0) //每5000次输出⼀次
{
printf("\r\n串⼝实验\r\n ");
}
if(times%200==0) //每200次输出⼀次
{
printf("请输⼊数据,以回车键结束\r\n");
}
if(times%30==0)LED0=!LED0; //每30次闪烁LED⼀次,提⽰系统正在运⾏ delay_ms(10);
}
李胜基辱华门}
}
⽂中函数和部分内容摘⾃正点原⼦stm32资料与官⽅库函数
⾃学新⼿,个⼈总结,如有出⼊,请多指教!
发布评论