hdahd 发表于 2022-7-31 16:16

串口通信-学习复盘

通信协议:通信数据以帧形式传递 [波特率、起始位、数据位、奇偶校验位、停止位]
以stm32f1系列芯片为例:共有5个串口,1-3是通用同步/异步串行接口USART(USART1-PA9、PA10 USART2-PA2、PA3 USART3-PB10、PB11) 4-5是通用异步串行接口UART(UART4-PC10、PC11 UART5-PC12、PD2)

hdahd 发表于 2022-7-31 16:17

代码实现:
(1)配置RX和TX引脚和串口初始化//先使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
//对io口进行配置
        //USART1_TX   GPIOA.9
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
        GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9

        //USART1_RX          GPIOA.10初始化
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
        GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//优先级配置
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器
//串口参数初始化
        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
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE);                  //使能串口1

hdahd 发表于 2022-7-31 16:18

(2串口中断函数,一般以0x0D(ascill:13表示回车\r),0x0a(ascill:
10表示换行\n)结尾,是一种自定义数据帧结束标志,同时帧头也是定义的一种开始标志,因为不知道串口什么时候发送数据,定义帧头,当接收到帧头,剩下的数据是我们需要的,以openmv为例.当接收到0x2C,0x012,在单片机中定义一个USART_Rx_Buf[]存储c(x)和c(y)的数据。

hdahd 发表于 2022-7-31 16:18

data=ustruct.pack("kkkkkk",
                     0x2C,
                     0x12,
                     int(cx),
                     int(cy),
                     0x0d,
                     0x0a)

hdahd 发表于 2022-7-31 16:19

串口中断服务函数:void USART1_IRQHandler(void)                        //串口1中断服务程序
{
        u8 Res;
        if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//接收中断(接收到的数据必须是0x0d 0x0a结尾)
                {
                Res =USART_ReceiveData(USART1);        //读取接收到的数据
               
                if((USART_RX_STA&0x8000)==0)//接收未完成
                        {
                        if(USART_RX_STA&0x4000)//接收到了0x0d
                                {
                                if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
                                else USART_RX_STA|=0x8000;        //接收完成了
                                }
                        else //还没收到0X0D
                                {       
                                if(Res==0x0d)USART_RX_STA|=0x4000;
                                else
                                        {
                                        USART_RX_BUF=Res ;
                                        USART_RX_STA++;
                                        if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收          
                                        }               
                                }
                        }                  
   }

hdahd 发表于 2022-7-31 16:20

第一次进入串口中断服务函数时,先判断是哪个串口接收到数据产生的中断,如果是,将接收到的1byte数据存储到变量里,接着判断是否还有数据没有接收完,如果接收到0x0d,0x0a,表示接收完成。USART_RX_STA有十六位,bit0-13表示有效数据,bit14表示接收到0x0d,bit15表示接收0x0a,接收完成。USART_GetFalgStatu
s函数用来检测串口中断标志位的状态,返回值为SET或者RESET。USART_GetITStatus函数用来判断中断标志位或是否发生中断,返回值为SET或者RESET。USART_ClearITPendingBit函数用在中断处理函数中对标志位进行清除操作。

hdahd 发表于 2022-7-31 16:21

(2)数据收发//发送一个字节
void usart_SendingByte(USART_TypeDef *p_USARTx,unsigned char ch)
{
while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)!=SET);
USART_SendData(p_USARTx,ch);
}
//USART_FLAG_TXE当发送数据寄存器中的数据已经取完,该标志置1,从而引发中断。

hdahd 发表于 2022-7-31 16:22

//发送字符串
void usart_sendingString(USART_TypeDef *p_USARTx,unsigned char *str)
{
        unsigned int k;
        do
        {
                usart_sending_byte(p_USARTx,*(str+k));
                k++;
        }
        while(*(str+k)!='\0');
        while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET)
        {}
}

/*USART_FLAG_TC当发送移位寄存器的一个字节数据已经通过TX脚一位一位移出去后,
该引脚被置1,从而引发事件中断*/

hdahd 发表于 2022-7-31 16:23

//接收一个字节数据
unsigned char usart_receive_byte(USART_TypeDef *p_USARTx,unsigned char ch)
{
        while(USART_GetFlagStatus(USARTx,USART_FLAG_RXNE)!=SET);
        USART_ClearITPendingBit(p_USARTx,USART_IT_RXNE);
        ch=USART_ReceiveData(USARTx);
        return ch;
}

hdahd 发表于 2022-7-31 16:23

//测试
#define max_Buff_len 8
unsigned char USART_Buffer;
unsigned char USART_Rx=0;
void USART_Send_Receive()
{
        if(USART_GetITStatus(USART1,USART_FLAG_RXNE)!=RESET)
        {
                USART_ClearITPendingBit(USART1,USART_IT_RXNE);
                Uart1_Buffer=USART_ReceiveData(USART1);
                Uart1_Rx++;
               
                if(Uart1_Buffer==0x0a||Uart1_Rx==Max_BUFF_Len)
                {
                        if(Uart1_Buffer==0x01)
                        {
                                printf("%s\r\n",Uart1_Buffer);
                                Uart1_Rx=0;
                        }
                        else
                        {
                                Uart1_Rx=0;
                        }
                }
        }

}

yiyigirl2014 发表于 2022-8-4 17:05

值得学习

wanduzi 发表于 2022-8-10 16:37

谢谢分享

dongnanxibei 发表于 2022-8-10 17:20

通信协议:通信数据以帧形式传递 [波特率、起始位、数据位、奇偶校验位、停止位],非常好。

lium 发表于 2022-8-10 21:51

为什么分开发?

yiy 发表于 2022-8-18 17:49

谢谢分享

Uriah 发表于 2022-10-1 13:14


USART1可以有多个时钟源

Bblythe 发表于 2022-10-1 16:13


通过访问寄存器来控制I2C1工作时钟的开启。

andygirl 发表于 2022-10-1 18:30

复盘这个词用的好

周半梅 发表于 2023-1-20 07:16


硬件设计和软件设计本来就是鱼和熊掌的关系,两者不可兼得

童雨竹 发表于 2023-1-20 08:09


事实上很多做项目的工程师本身自己也会在用
页: [1]
查看完整版本: 串口通信-学习复盘