关于STM32F103C8T6 应用的一些坑

关于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; // 必须默认接收状态
}
看起来没啥问题 但是数据死活接收不到。原因就在上面的发送使能引脚的初始化中,推挽输出错误的写成复用推挽输出。导致发送使能引脚一直是高电平,发送状态。所以才一直接收不到数据。

以上是我目前遇到的最大的三个坑,每个坑都花费了我巨大的时间去查找,因此记录下来与君共勉。。。

你可能感兴趣的:(笔记,stm32,单片机,arm)