STM32的PB3口不能拉低 PB4口不能拉高 其他口貌似都可以 怎么会
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32的PB3口不能拉低 PB4口不能拉高 其他口貌似都可以 怎么会相关的知识,希望对你有一定的参考价值。
参考技术A 貌似JTAG接口,建议关掉JTAG功能试试。stm32 普通IO口模拟串口通信
普通IO口模拟串口通信
-
串口通信协议
-
串口传输 默认 波特率9600 1起始位 1停止位 其他0 数据位是8位(注意图上的给错了)。
- 传输时,从起始位开始,从一个数据的低位(LSB)开始发送,如图从左向右的顺序,对电平拉高或拉低,最后停止位时拉高。
- 波特率大小,改变延时时间即可。例如9600 波特率 根据公式 : 1/9600=0.000104s(大致) 也就是说每发送1bit延时104us (下面我用9600波特率来说,代码用的是19200)
- 串口发送 将电平拉低 延时104us(视为 起始位 0 传输数据正式开始) 其中数据我发送的是16进制数据(8bit 一字节 例如10001000) 将想要发的数据按照二进制的‘0’‘1’高低电平的方式,每发送1bit 延时104us 直到发送完到终止位 将电平拉高视为一包数据传输结束。(根据需求更改即可)
- 串口接收 (稍微麻烦一些) 两种方法:第一种可以用定时中断,每隔104us开启一次定时中断,中断函数内进行高低电平判断,将这些bit存储最后转换成需要的数据。第二种,用外部中断处理函数,外部中断设置同时开启上升沿下降沿,思路:根据上升下降的电平跳变分析。比如说,触发外部中断后检测电平高低,记录一下当前时间,然后再进入外部中断后 计算出总共几个bit (两个沿跳变之间的时间 =现在记录的时间 — 之前记录的时间 bit=这个时间/104us) ,知道这个就可以转换数据了。
- 定时中断逻辑相对外部中断而言简单好写,但是数据多的时候准确率下降很多,容易丢数据(因为定时中断毕竟用计时开启中断,不可能时间准确每104us开启一次,数据一多时间误差大,自然丢包。可以尝试每发一串数据,重新计时校准一次)。外部中断较为准确,检测的高低电平跳变较为明显唯一,一个跳变就是一个数据,只是分析情况比较多。
//IO模拟串口初始化
1 void IRrec_Init() 2 3 4 EXTI_InitTypeDef EXTI_InitStructure; 5 NVIC_InitTypeDef NVIC_InitStructure; 6 GPIO_InitTypeDef GPIO_InitStructure; 7 8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能GPIOC时钟 9 10 11 //IR TX C9 使能 12 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 13 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 14 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 15 GPIO_Init(GPIOC, &GPIO_InitStructure); 16 GPIO_SetBits(GPIOC, GPIO_Pin_9);// 引脚拉高 17 18 19 //IR RX C8 20 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); 21 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 22 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 23 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 24 GPIO_Init(GPIOC, &GPIO_InitStructure); 25 GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource8); 26 27 EXTI_InitStructure.EXTI_Line=EXTI_Line8; 28 EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; 29 EXTI_InitStructure.EXTI_Trigger= 30 EXTI_Trigger_Rising_Falling; 31 EXTI_InitStructure.EXTI_LineCmd=ENABLE; 32 EXTI_Init(&EXTI_InitStructure); 33 34 NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn; 35 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; 36 NVIC_InitStructure.NVIC_IRQChannelSubPriority=2; 37 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; 38 NVIC_Init(&NVIC_InitStructure); 39 40
1 void IR_SendByte(u8 val)//发送bit位 2 3 u16 i; 4 5 IRSEND=0;//拉低 开始传输 6 SysTick_Delay_Us(53);//波特率根据延时在设置 19200波特率 7 8 for(i=0;i<8;i++) 9 10 if(val&0x1) 11 12 IRSEND=1; 13 14 else 15 16 IRSEND=0; 17 18 19 val>>=1; 20 SysTick_Delay_Us(53); 21 22 23 IRSEND=1; 24 SysTick_Delay_Us(53); 25 26 27 28 void IR_SendStr(u8*st,u16 len)//在这填入16位数据即可 29 int i=0; 30 while ((len--)!=0) 31 32 IR_SendByte(st[i]); 33 i++; 34 35 36
1 u8 IRREC_RX_BUF[64]=0; //接收缓冲,最大64个字节. 2 //接收到的数据长度 3 u8 IRREC_RX_CNT=0; 4 5 char rebit=stopbit;//记录接收一个字节的二进制位所处何种位置 6 u8 Recev[8]=0;//记录接收的一个字节的二进制流 7 8 static volatile unsigned long long m_rx_previous_time = 0;//上一次进入中断时间 9 static volatile unsigned char m_rx_begin_f = 0;//开始一个字节的接收标志 0-无数据开始接收 1-有数据开始接收 10 void EXTI9_5_IRQHandler(void) 11 12 if(EXTI_GetITStatus(EXTI_Line8)!=RESET) 13 14 unsigned char skip_index = 0; 15 unsigned char i = 0; 16 unsigned char temp_bin = 0;//用于记录二进制值 17 unsigned long long current_time = sys_micros();//记下此刻时间 18 unsigned short interval_time = current_time - m_rx_previous_time;//计算一个状态持续的时长 19 m_rx_previous_time = current_time;//为下次计算时长做准备 20 21 //当前未开始一个字节的接收且此时为下降沿 22 if(rebit == 10)//10 当数据不合法时或者结束传输时 rebit值设为10 23 24 if(!PCin(8))//下降沿 25 26 rebit = 0;//记下开始接收 27 m_rx_begin_f = 1; 28 debug_led(1,LED_TOGGLE); 29 30 31 //已经开始接收 32 else 33 34 //上一状态为起始位 35 if(!rebit)//起始位0 36 37 //计算二进制数据的个数 38 skip_index = (interval_time/50)-1; 39 40 //个数合法 41 if(skip_index <= 9) 42 43 //根据状态保持时间更新接收值 44 for(i = 0;i < skip_index;i++) 45 46 Recev[i] = 0; 47 48 49 50 //更新接收二进制位的下标 51 rebit = skip_index; 52 53 54 //不合法-重新接收 55 else 56 57 rebit = 10; 58 m_rx_begin_f = 0; 59 60 61 62 63 //上一状态为数据位 64 else 65 66 //计算二进制数据的个数 67 skip_index = interval_time/50; 68 69 //数据不合法-重新接收 70 if((skip_index+rebit) > 9)//所处位置+数据个数 判断数据是否超10 合法判断 71 72 //printf("skip_index %d rebit=%d \\r\\n",skip_index,rebit); 73 rebit = 10; 74 m_rx_begin_f = 0; 75 debug_led(3,LED_TOGGLE); 76 77 //数据合法 78 else 79 80 //当前为高电平 81 if(PCin(8)) 82 83 temp_bin = 1;//0 84 85 else 86 87 temp_bin = 0;//1 change 88 89 debug_led(2,LED_TOGGLE); 90 for(i = 0;i < skip_index ;i++)//根据几个数据 给予相应的位 91 92 Recev[rebit+i+1] = temp_bin;//change +1 93 rebit++; 94 95 96 97 98 //数据已接收至结束位 99 if(rebit >= 8 )//=8>? 100 101 if(IRREC_RX_CNT < 64) 102 103 IRREC_RX_BUF[IRREC_RX_CNT++] = (Recev[7] << 7) |(Recev[6] << 6)| (Recev[5] << 5)| (Recev[4] << 4)| (Recev[3] << 3) |(Recev[2] << 2) |(Recev[1] << 1) |Recev[0]; 104 105 106 rebit = 10; 107 m_rx_begin_f = 0; 108 109 110 111 112 113 114 115 116 #endif 117 EXTI_ClearITPendingBit(EXTI_Line8);//清除中断挂起标志位 118 119 120 121
用于知识梳理积累,写的比较随意
有问题可以发邮箱联系我 udpmeettcp@163.com
以上是关于STM32的PB3口不能拉低 PB4口不能拉高 其他口貌似都可以 怎么会的主要内容,如果未能解决你的问题,请参考以下文章
STM32库中关于GPIO_PinRemapConfig函数的使用