关于STM32F103C8T6 应用的一些坑
1、在配置按键中断时天真的以为每个IO口都对应着一个中断线,结果发现总有一些按键死活进不了中断,开始以为是我代码问题,反反复复的去看代码,后来发现只要是多个按键一起初始化的,能进中断的只有最后一个。然后就去翻各种资料,看DATASHEET,终于找到了原因。
之前按键中断初始化代码如下:
void key_exit(){
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启中断时钟
//上
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);
EXTI_InitStructure.EXTI_Line=EXTI_Line1; //中断初始化
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //上下降沿有效
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
//下
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
EXTI_InitStructure.EXTI_Line=EXTI_Line0;
EXTI_Init(&EXTI_InitStructure);
//左
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource3);
EXTI_InitStructure.EXTI_Line=EXTI_Line3;
EXTI_Init(&EXTI_InitStructure);
//右
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource2);
EXTI_InitStructure.EXTI_Line=EXTI_Line2;
EXTI_Init(&EXTI_InitStructure);
//窄角
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource2);
EXTI_InitStructure.EXTI_Line=EXTI_Line2;
EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);
EXTI_InitStructure.EXTI_Line=EXTI_Line0;
EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource10);
EXTI_InitStructure.EXTI_Line=EXTI_Line10;
EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource11);
EXTI_InitStructure.EXTI_Line=EXTI_Line11;
EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource12);
EXTI_InitStructure.EXTI_Line=EXTI_Line12;
EXTI_Init(&EXTI_InitStructure);
//色温变低
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13);
EXTI_InitStructure.EXTI_Line=EXTI_Line12;
EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);
EXTI_InitStructure.EXTI_Line=EXTI_Line14;
EXTI_Init(&EXTI_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource15);
EXTI_InitStructure.EXTI_Line=EXTI_Line15;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //抢占中断优先级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; //抢占中断优先级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //抢占中断优先级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //抢占中断优先级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //抢占中断优先级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x04;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
资料上是这么说的:
stm32内部资源有限,因此产生了很多共用资源,其中外部中断也是其中之一。外部中断的共用资源主要包括:
(1)不同端口、同一pin口,共用一个中断线:如PA1、PB1、PC1共用外部中断线1——EXTI_Line1;
(2)不同pin口、同一端口:这个都不用说,PA1、PA2、PA3这些共用的是同一个端口寄存器之类的;
(3)同一pin口共用一个中断线,但16个中断线却只共用7个中断服务函数:其中中断线EXTI_Line0-4独立拥有一个中断服务,中断线5-9共用一个中断服务函数,中断线10-15共用一个中断服务函数。
————————————————
原文链接:https://blog.csdn.net/u013400631/article/details/106018645/
最终把一些共用中断线的按键改为轮询,才将需要的功能实现。
2、将项目大概功能完成后,开始处理LED的工作,同样单纯的认为只是点个灯而已,于是便像之前一样 ,弄个结构体,初始化时钟,推挽输出,结构体初始化。感觉这就行了,没啥东西。但当我将代码下载到板子后,直接怀疑人生了。点灯死活点不亮,开始怀疑是硬件问题 ,以为是灯珠烧了,或者线路问题,一顿查找发现就是代码问题。然后又回头去翻资料,找了好久才明白其中的原因。
如下:
STM3210X系列的芯片在复位后,会将PA13/14/15 PB3/4默认配置为JTAG功能。
意思就是说引脚的功能被占用了,解决这个问题只需两行代码
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 这个时钟一定要开启不然没有效果
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); 注意!!!!!
这里的 GPIO_Remap_SWJ_JTAGDisable 千万不要搞成GPIO_Remap_SWJ_Disable
前者是关闭JTAG保留SWJ功能,后者是把两个调试功能全部关掉,写错的后果就是你的程序就烧不进去了。不过网上也有好多解决的办法,但是安全起见 还是注意点好。
还有就是最好不要直接复制别人的代码,直接复制会产生你想象不到的问题。
比如下面这个485串口的初始化
void uart_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//USART1_RX GPIOA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//send enable
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PA12 发送使能
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
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);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
RS485_TX_EN = 0; // 必须默认接收状态
}
看起来没啥问题 但是数据死活接收不到。原因就在上面的发送使能引脚的初始化中,推挽输出错误的写成复用推挽输出。导致发送使能引脚一直是高电平,发送状态。所以才一直接收不到数据。
以上是我目前遇到的最大的三个坑,每个坑都花费了我巨大的时间去查找,因此记录下来与君共勉。。。