【WCH蓝牙系列芯片】-基于CH32V208开发板—RS-485串口收发数据通信
------------------------------------------------------------------------------------------------------------------------------------
整个RS-485的通信原理,可以参考https://www.cnblogs.com/ZYL-FS/p/18592401
先看一下硬件原理图,485电平转换芯片硬件连接,CH32V208使用串口1的PA9(TX)和PA10(RX)还有一个收发模式的控制脚PA1。将CH32V208的RXD(PA1)直接连接485芯片的RO引脚;通过TXD(PA9)直接连接485芯片的DI引脚,该485芯片处于发送模式还是接收模式的选择位是DE/!RE,一般情况下把这两个引脚接在一起,只用CH32V208的一个引脚PA1直接连接TNOW0.
当CH32V208的PA1输出的信号TNOW0为高电平,则芯片处于发送模式
当CH32V208的PA1输出的信号TNOW0为低电平,则芯片处于
在程序串口初始中,配置PA1为复用推挽输出,还有串口脚PA9,PA10,分别配置为复用推挽输出和浮空输入模式。并直接设置PA1引脚是低电平,让485芯片默认是接收模式。
RS485_Send_Data是485发送数据函数,将PA1设置为高电平,为发送模式
RS485_Receive_Data是485查询接收到的数据,将PA1设置为低电平,为接收模式
在主程序中,先485那端先接收串口发送的数据,然后将接收到数据rx485buf再全都复制一遍到tx485buf中,再利用RS485_Send_Data函数,将发送的数据,再回传到串口,并显示。可以通过下端的串口调试工具来观察。串口打印那段也可以看到485那端接收的数据。
程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | #include "debug.h" #define buffer_len 256 u8 USART_Rbuffer_Num = 0; u8 USART_Tbuffer_Num = 0; u8 USART_Rbuffer[buffer_len]; //接收缓冲区数组 void USART1_Init(uint32_t bound) { GPIO_InitTypeDef GPIO_InitStructure={0}; USART_InitTypeDef USART_InitStructure={0}; NVIC_InitTypeDef NVIC_InitStructure={0}; /* 打开GPIO和USART部件的时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //485_RE_DE控制引脚 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; //模式选择PA1(CS) GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; // IO口频率 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; // 复用推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure); // 初始化 /* 配置GPIO的模式和IO口 */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; // 串口输出PA9(TX) GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; // IO口频率 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure); // 初始化 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; // 串口输入PA10(RX) GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(GPIOA,&GPIO_InitStructure); // 初始化 /* 配置串口硬件参数 */ USART_DeInit(USART1); USART_InitStructure.USART_BaudRate = bound; /* 波特率 */ 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(USART1, &USART_InitStructure); /* 使能串口1中断 */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_ClearFlag(USART1, USART_FLAG_RXNE); USART_ClearITPendingBit(USART1, USART_IT_RXNE); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* 使能串口空闲中断 */ USART_Cmd(USART1, ENABLE); /* 使能串口 */ //默认接收 GPIO_ResetBits(GPIOA, GPIO_Pin_1); //设置RE、DE引脚低电平,接收状态 } // 用于发送单个字节的数据 void USARTx_SendByte(USART_TypeDef* pUSARTx, uint8_t data) { USART_SendData(pUSARTx, data); while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } //用于发送一个字符串 void USARTx_SendStr(USART_TypeDef* pUSARTx, char *str) { uint8_t i = 0; do { USARTx_SendByte(pUSARTx, *(str+i)); i++; } while (*(str+i) != '\0' ); while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET); } //RS485发送len个字节. //buf:发送区首地址 //len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节) void RS485_Send_Data(u8 *buf,u8 len) { GPIO_SetBits(GPIOA, GPIO_Pin_1); //设置为发送模式 u8 t; for (t=0;t<len;t++) //循环发送数据 Q { while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); // 等待USART1的发送完成标志(TC)被设置 USART_SendData(USART1,buf[t]); // 将buf数组中的第t个字节发送出去 } while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); // 发送完所有数据后,这个循环再次等待USART1的发送完成标志被设置 USART_Tbuffer_Num=0; // 清空发送缓冲区 } //RS485查询接收到的数据 //buf:接收缓存首地址 //len:读到的数据长度 void RS485_Receive_Data(u8 *buf,u8 *len) { GPIO_ResetBits(GPIOA, GPIO_Pin_1); //设置为接收模式 u8 rxlen=USART_Rbuffer_Num; // USART接收缓冲区中的数据数量 u8 i=0; *len=0; //默认为0 Delay_Ms(10); //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束 if (rxlen==USART_Rbuffer_Num&&rxlen) //接收到了数据,且接收完成了 { for (i=0;i<rxlen;i++) { buf[i]=USART_Rbuffer[i]; // USART接收缓冲区中的数据复制到用户提供的缓冲区buf中 } *len=USART_Rbuffer_Num; //记录本次数据长度 USART_Rbuffer_Num=0; //清零 } } /********************************************************************* * @fn main * * @brief Main program. * * @return none */ int main( void ) { u8 value; // 存储接收到的数据长度 u8 i=0; u8 tx485buf[9]={9,8,7,6,5,4,3,2,1}; // 存储要发送的数据 u8 rx485buf[9]={0}; // 用于存储接收到的数据 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置中断的优先级 SystemCoreClockUpdate(); // 更新系统核心时钟 Delay_Init(); USART_Printf_Init(115200); // 串口打印初始化 printf( "USART Interrupt TEST\r\n" ); USART1_Init(115200); // 串口1初始化 while (1) { //接收 RS485_Receive_Data(rx485buf,&value); // 调用RS485_Receive_Data函数接收数据,存储到rx485buf数组中,并将接收到的数据长度存储在value变量中 printf( "value1=%d\r\n" ,value); // 打印接收到的数据长度 if (value) //接收到有数据 { for (i=0;i<value;i++) { tx485buf[i]=rx485buf[i]; // 将rx485buf中的数据复制到tx485buf中 printf( "receive=%x\r\n" ,(u8)rx485buf[i]); // 打印每个接收到的数据字节 } } Delay_Ms(1000); RS485_Send_Data(tx485buf,value); // 发送tx485buf数组中的数据,长度为9个字节 } } void USART1_IRQHandler( void ) __attribute__((interrupt( "WCH-Interrupt-fast" ))); void USART1_IRQHandler( void ) { if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //中断产生 { USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中断标志 USART_Rbuffer[USART_Rbuffer_Num] = USART_ReceiveData(USART1); //接收数据 USART_Rbuffer_Num++; } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具