[其他ST产品]

串口通信-学习复盘

[复制链接]
459|17
手机看帖
扫描二维码
随时随地手机跟帖
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[USART_RX_STA&0X3FFF]=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[max_Buff_len];
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[Uart1_Rx]=USART_ReceiveData(USART1);
                Uart1_Rx++;
               
                if(Uart1_Buffer[Uart1_Rx-1]==0x0a||Uart1_Rx==Max_BUFF_Len)
                {
                        if(Uart1_Buffer[0]==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 | 显示全部楼层

事实上很多做项目的工程师本身自己也会在用

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

58

帖子

0

粉丝