当前位置: 首页 > news >正文

如何做网站管理/江门seo外包公司

如何做网站管理,江门seo外包公司,成都建筑公司排名前十,南宁市哪里有帮搞网页设计的stm32g0 GPIO模拟串口UART通讯 代码下载https://download.csdn.net/download/weixin_42401119/72340612​​​​​​ 前面博客有模拟串口的的代码,是采用延时等待的方法,CPU存在空转情况,浪费CPU资源,并且期间不能有太多中断处理…

stm32g0 GPIO模拟串口UART通讯 代码下载https://download.csdn.net/download/weixin_42401119/72340612​​​​​​

前面博客有模拟串口的的代码,是采用延时等待的方法,CPU存在空转情况,浪费CPU资源,并且期间不能有太多中断处理,以免影响模拟串口的时序。

本文用stm32G0的GPIO模拟串口通信,使用定时器和外部中断,不用延时等待,不浪费CPU资源。

使用资源:一个定时器,一个普通IO口(TX),一个带外部中断的IO口(RX)。

实现原理:

1、发送部分,通过定时器控制波特率,在定时器中断函数中改变IO口电平来发送数据,定时器中断优先级设置最高,可以保证时序的精确度。

2、接收部分,通过外部下降沿中断,识别起始位,定时器控制波特率,定时器中断优先级设置最高,在定时器中断函数读取电平,也是在电平中间位置读取,大大降低误码率。

3、关于串口程序都在定时器中断函数处理,不用延时等待,发送和接收完成后关闭定时器中断,完全不浪费时间,大大提高CPU使用效率。

此代码暂时没用在量产产品上,不过四个小时100ms的收发测试,还没发现问题,也请广大网友帮忙验证,一起找bug。

注意问题:

1、经过测试,发送波特率最高为256000,接收波特率最高为19200,建议波特率不高于19200。

2、数据格式为:1起始位+8数据位+1停止位,半双工通信,不能同时收发。

3、程序只能接收定长的数据,如果需要接收不定长数据,请网友自行修改(接收倒计时中,超时则认为一帧数据接收完成,再统计数据长度和校验)。

4、定时器中断优先级设置为最高,可以保证时序准确。

5、我的数据包帧头是0xAA,帧尾0x0D,校验值是除了帧尾所有数据的累加和,帧头,帧尾和校验根据用户需求修改。

6、程序用的是LL库。

以下是主要代码:

gpio.c

//TXD为发送端口,配置为普通推挽输出。//RXD为接收端口,配置为外部下降沿中断。void MX_GPIO_Init(void)
{LL_EXTI_InitTypeDef EXTI_InitStruct = {0};LL_GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);/**/LL_GPIO_SetOutputPin(TXD_GPIO_Port, TXD_Pin);/**/LL_EXTI_SetEXTISource(LL_EXTI_CONFIG_PORTB, LL_EXTI_CONFIG_LINE7);/**/EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_7;EXTI_InitStruct.LineCommand = ENABLE;EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_FALLING;LL_EXTI_Init(&EXTI_InitStruct);/**/LL_GPIO_SetPinPull(RXD_GPIO_Port, RXD_Pin, LL_GPIO_PULL_UP);/**/LL_GPIO_SetPinMode(RXD_GPIO_Port, RXD_Pin, LL_GPIO_MODE_INPUT);/**/GPIO_InitStruct.Pin = TXD_Pin;GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;LL_GPIO_Init(TXD_GPIO_Port, &GPIO_InitStruct);/* EXTI interrupt init*/NVIC_SetPriority(EXTI4_15_IRQn, 0);NVIC_EnableIRQ(EXTI4_15_IRQn);}

tim.c

//系统时钟是64MHz,不分频,即每(1/64)us加1,向上计数,从0加到6667用时104us,对应波特率9600。void MX_TIM3_Init(void)
{/* USER CODE BEGIN TIM3_Init 0 *//* USER CODE END TIM3_Init 0 */LL_TIM_InitTypeDef TIM_InitStruct = {0};/* Peripheral clock enable */LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);/* TIM3 interrupt Init */NVIC_SetPriority(TIM3_IRQn, 0);NVIC_EnableIRQ(TIM3_IRQn);/* USER CODE BEGIN TIM3_Init 1 *//* USER CODE END TIM3_Init 1 */TIM_InitStruct.Prescaler = 0;TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;TIM_InitStruct.Autoreload = 6667;                    //波特率9600TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;LL_TIM_Init(TIM3, &TIM_InitStruct);
//  LL_TIM_EnableARRPreload(TIM3);                    //注意不能同步装载LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);LL_TIM_DisableMasterSlaveMode(TIM3);/* USER CODE BEGIN TIM3_Init 2 *//* USER CODE END TIM3_Init 2 */}void USER_TIM3_CONFIG(void)//开启定时器中断
{LL_TIM_EnableIT_UPDATE(TIM3);LL_TIM_EnableCounter(TIM3);
}

uart_io.c

/**************************发送代码**************************/
void UART_IO_Tx_Start(uint32_t baud)//每次调用该函数就会启动发送程序,发送完成自动结束。
{uint32_t autoreload=0;autoreload=d_systemclock/baud;//根据波特率计算装载值LL_TIM_SetAutoReload(TIM3,autoreload);LL_TIM_EnableIT_UPDATE(TIM3);//使能定时器中断LL_TIM_EnableCounter(TIM3);  //使能计数Tx_status=0;                 //发送时序清零,在定时器中开始发送。
}uint8_t TxBuff[TXD_size]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
uint8_t Tx_status;//用于控制发送时序
void UART_IO_TxProcess(uint8_t *buff,uint8_t size)
{static uint8_t byte_cnt;    //已发送数据个数计数static uint8_t bit_cnt;     //已发送位数计数static uint8_t Txdata,byte; //数组中要发送的数据,数据中间变量switch(Tx_status){case 0x00:byte_cnt=0;//准备发送,计数值清零,发送前TXD为高电平TXD_H();Tx_status++;break;case 0x01:TXD_L();    //发送起始位bit_cnt=0;  Txdata=buff[byte_cnt];Tx_status++;break;case 0x02:if(bit_cnt==8)//完成一个byte的发送{bit_cnt=0;TXD_H();byte_cnt++;if(byte_cnt==size)//完成一帧数据的发送{Tx_status=0x03;LL_TIM_DisableIT_UPDATE(TIM3);//发送完成,关闭定时器中断,不浪费资源LL_TIM_DisableCounter(TIM3);LL_EXTI_EnableFallingTrig_0_31(LL_EXTI_LINE_7);//开启接收中断}elseTx_status=0x01;}else    //逐位发送数据{	byte=Txdata>>bit_cnt;if(byte&0x01)TXD_H();elseTXD_L();bit_cnt++;}break;case 0x03:TXD_H();break;//数据发送完成,TXD拉高。default:TXD_H();break;}
}/**************************接收代码**************************/
void UART_IO_Rx_Start(uint32_t baud)//在外部中断中调用该函数就会启动接收程序。
{uint32_t autoreload=0;autoreload=(d_systemclock/baud/2)*3;//识别到外部中断,直接跳过起始位,在第一个bit中间位置读数据,所以是3/2的时间LL_TIM_SetCounter(TIM3,0);//清零之前的计数值,保证时序准确LL_TIM_SetAutoReload(TIM3,autoreload);LL_TIM_EnableIT_UPDATE(TIM3);    //打开定时器中断LL_TIM_EnableCounter(TIM3);      //开始计数B_RXD_Falling=1;                 //有下降沿的标志
}uint8_t	B_RXD_Falling;
uint8_t R_RXD_countdown;//接收过程倒计时,放在系统定时器systick中,每1ms减一,直到0
uint8_t B_RXD_decode;   //数据解码标志位,数据格式和校验正确,置1
#define Set_Rx_Countdown()		R_RXD_countdown=10//10ms内没接收到字节,认为本次接收结束。
#define Reset_Rx_Countdown()	R_RXD_countdown=0
uint8_t RxBuff[RXD_size]={0};
void UART_IO_RxProcess(uint8_t *buff,uint8_t size,uint32_t baud)
{static uint8_t Rxdata;static uint8_t byte_cnt,bit_cnt;static uint8_t checksum;static uint8_t Rx_status;uint32_t autoreload=0;if(B_RXD_Falling)//有下降沿{if(!R_RXD_countdown)//倒计时结束了,接收数据是非连续,清零计数值,开始接收新一帧数据。{bit_cnt=0;byte_cnt=0;Rx_status=0;checksum=0;}Set_Rx_Countdown();//如果数据是连续接收的,则倒计时不会结束if(!Rx_status)//接收新字节前,清零计数值{LL_TIM_SetCounter(TIM3,0);autoreload=d_systemclock/baud;//之前是3/2的波特率,跳过起始位后,恢复正常的波特率LL_TIM_SetAutoReload(TIM3,autoreload);Rxdata=0;bit_cnt=0;Rx_status++;}if(Rx_status){Rxdata>>=1;//接收位if(LL_GPIO_IsInputPinSet(RXD_GPIO_Port,RXD_Pin)==SET)Rxdata|=0x80;if(bit_cnt<7)bit_cnt++;else{buff[byte_cnt]=Rxdata;//接收到一个字节后放入数组中if(byte_cnt<(size-2))checksum+=buff[byte_cnt];//计算校验和byte_cnt++;if(byte_cnt==size)//接收完一帧数据{if((buff[0]==d_head)&&(buff[size-1]==d_tail)&&(buff[size-2]==checksum))B_RXD_decode=1;//数据格式,校验和正确}Rx_status=0;B_RXD_Falling=0;LL_TIM_DisableIT_UPDATE(TIM3);LL_TIM_ClearFlag_UPDATE(TIM3);LL_TIM_DisableARRPreload(TIM3);LL_TIM_DisableCounter(TIM3);LL_EXTI_EnableFallingTrig_0_31(LL_EXTI_LINE_7);//完成一个字节的接收,重新开始起始位中断}}}
}

stm32g0xx_it.c

void SysTick_Handler(void)//1ms
{/* USER CODE BEGIN SysTick_IRQn 0 */static uint16_t TIM_1s;TIM_1s++;if(R_RXD_countdown)R_RXD_countdown--;if(TIM_1s>999){TIM_1s=0;B_TIM1_JC=1;}/* USER CODE END SysTick_IRQn 0 *//* USER CODE BEGIN SysTick_IRQn 1 *//* USER CODE END SysTick_IRQn 1 */
}void EXTI4_15_IRQHandler(void)
{/* USER CODE BEGIN EXTI4_15_IRQn 0 *//* USER CODE END EXTI4_15_IRQn 0 */if (LL_EXTI_IsActiveFallingFlag_0_31(LL_EXTI_LINE_7) != RESET){LL_EXTI_ClearFallingFlag_0_31(LL_EXTI_LINE_7);/* USER CODE BEGIN LL_EXTI_LINE_7_FALLING */if(LL_GPIO_IsInputPinSet(RXD_GPIO_Port,RXD_Pin)==RESET){LL_EXTI_DisableFallingTrig_0_31(LL_EXTI_LINE_7);UART_IO_Rx_Start(d_baud);}/* USER CODE END LL_EXTI_LINE_7_FALLING */}/* USER CODE BEGIN EXTI4_15_IRQn 1 *//* USER CODE END EXTI4_15_IRQn 1 */
}void TIM3_IRQHandler(void)
{/* USER CODE BEGIN TIM3_IRQn 0 */if (LL_TIM_IsActiveFlag_UPDATE(TIM3)==SET)  {  LL_TIM_ClearFlag_UPDATE(TIM3);UART_IO_RxProcess(RxBuff,RXD_size,d_baud);UART_IO_TxProcess(TxBuff,TXD_size);}	/* USER CODE END TIM3_IRQn 0 *//* USER CODE BEGIN TIM3_IRQn 1 *//* USER CODE END TIM3_IRQn 1 */
}

user_define.h

#define d_head				0xAA    //帧头
#define d_tail				0x0D    //帧尾
#define RXD_size			14      //接收字节数
#define TXD_size			16      //发送字节数
#define d_baud				9600    //波特率
#define d_systemclock	    64000000//系统时钟#define TXD_H()	LL_GPIO_SetOutputPin(TXD_GPIO_Port, TXD_Pin)
#define TXD_L()	LL_GPIO_ResetOutputPin(TXD_GPIO_Port, TXD_Pin)

main.c

int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);/* System interrupt init*//* SysTick_IRQn interrupt configuration */NVIC_SetPriority(SysTick_IRQn, 3);/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit */SysTick_Config(SystemCoreClock/1000);NVIC_SetPriority(SysTick_IRQn,3);NVIC_EnableIRQ(SysTick_IRQn);/* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_TIM1_Init();MX_TIM3_Init();/* USER CODE BEGIN 2 */USER_TIM1_CONFIG();USER_TIM3_CONFIG();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){if(B_TIM1_JC){B_TIM1_JC=0;}if(B_RXD_decode)//接收到正确的数据并处理{B_RXD_decode=0;UART_IO_Tx_Start(d_baud);//接收到数据并发送}/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

http://www.jmfq.cn/news/4915567.html

相关文章:

  • 网站编辑做app/投资网站建设方案
  • 网站建设报价东莞/每日新闻播报
  • 暖通设计网站推荐/谷歌seo详细教学
  • 网站建设佰金手指科杰十一/网络建站平台
  • 0基础做下载网站/优化大师是什么软件
  • 海口房产网站建设/长春做网站推荐选吉网传媒好
  • 手机做图片的网站/个人网站模板
  • 网站开发技术及特点/在线培训系统平台
  • wordpress 前台评论/优化法治化营商环境
  • 织梦移动端网站模板下载/网络推广山东
  • vps网站管理助手教程/重庆关键词快速排名
  • 制作公司工作网站/腾讯新闻发布平台
  • 网页设计与制作怎样添加图片/关键词优化排名用哪些软件比较好
  • wordpress在线演示/北京seo技术
  • 施工企业工作分解结构/保定百度首页优化
  • 北京建设网站公司/线上怎么做推广和宣传
  • 在线做动漫图片视频在线观看网站/可以商用的电视app永久软件
  • 网站框架有哪些/凡科建站登录官网
  • 简述电子商务网站的建站流程/百度ai人工智能
  • 网站特点怎么写/湖南seo快速排名
  • wordpress自动tag/成都seo优化排名推广
  • 林壑地板北京网站建设/全网营销推广公司
  • 给人做网站赚钱/公司推广渠道有哪些
  • 京东网站建设策略/百度app最新版本
  • 网站开发笔记本要什么配置/网站优化策略分析论文
  • 在床上做很黄很暴力网站/软文发稿公司
  • 微网站开发教材/百度客服怎么联系
  • iis做外网站点/备案查询平台官网
  • 桂林网站设计公司/如何做网站网页
  • 有没有做家具特卖的网站/商丘seo博客