文章目录[隐藏]
寄存器表示C语言的对应关系
- R0: 存储C语言函数返回值
- R14 : 存储C的函数返回地址
- R15 : 当前执行程序的代码地址
ARM的常用指令
- 将数据加载到寄存器:MOV/LDR
- 子程序调用指令: BL
- 软中断调用指令: SWI
RS232通信标准的电气规范
逻辑0、逻辑1的表示方式
在TxD
和RxD
上:
逻辑1(MARK)=-3V~-15V
逻辑0(SPACE)=+3~+15V
常见ARM模块的名称
- RCC : 系统复位时钟控制器
- GPIO:通用功能输入输出控制器
- EXTI: 外部中断控制器
- USART: 通用异步/同步收发器
零散知识点
-
从系统0x0地址上取出来的值赋值给SP,做为C语言的栈地址
-
从系统0x4地址上取出来的值赋值给PC,做为复位异常的入口地址
-
ATPCS中,栈的操作方式是满递减方式
-
stm32中断优先级设置为第2组的话,抢占优先级可以配置为0,1,2,3
-
驱动无速度要求的外设时,如发光二极管,GPIO推荐配置速度为2MHZ即可
-
systick
时钟控制模块,采用了24bit的计数器 -
用来将NVIC寄存器设置为缺省函数名的函数是:
NVIC_Deinit
-
用来设置NVIC寄存器为特定值的函数是:
NVIC_Init
-
stm32f103有4种输出模式:开漏输出、开漏复用输出、推挽式输出、推挽式复用输出
-
RS232中,TXD和RXD相连,RXD和TXD相连
-
ADC转换的步骤是 采样、量化、编码
-
CortexM
体系结构编程模型支持2种工作模式空间 -
CortexM
体系结构支持thumb2指令集 -
ARM公司规定用R15表示程序运行的地址寄存器
-
在stm32F103中GPIO控制器挂载在APB2时钟总线上
-
中断处理函数和普通函数的执行方式是不一样的
-
输入浮空模式下,外部引脚的电压是不确定的
-
stm32F103的内部SRAM基地址是0x20000000
-
CMSIS是ARM公司推出的库接口标准
有效立即数的判断
立即寻址
在立即寻址中,操作数由操作指令本身给出,这个操作数也就是我们说的立即数,举例:
ADD R0, R1, #5 ;R0=R1+5
MOV R0, #0x55 ;R0=0x55
这里的5
和0x55
就是这两条指令的立即数
立即数的形式
- 0x 或 & 表示十六进制数
- 0b 表示二进制数
- 0d 或缺省表示十进制数
立即寻址指令
格式
32为的立即寻址指令的格式如图
但是我们只用关心后面的rotate
和immediate
部分即可,因为这才是立即数的组成元素
立即数构成
rotate
+immediate
,前者是移位操作的移位数,后者是立即数的部分(完整的要通过移位之后构成)
一个立即数是由32位构成的所以我们计算立即数的时候要把前置0补齐
合法立即数
如果一个立即数存在一个rotate
使得immediate
循环右移2*roate
次(roate
>0)和当前的立即数相等,那么就表示这个立即数是合法的
一个判断立即数的小trick:
看一个指令的从最低位到第一个为1的位数(不包含),如果有奇数个0那么就不是立即数,如果有偶数个0那么就是立即数(其实也就是利用了这里的2倍的性质,感兴趣可以证明一下)
eg:
0000 0000 0000 0000 0000 0011 1111 0010 //不是立即数,因为有一个0
0000 0000 0000 0000 0000 0011 1111 0100 //是立即数,有两个0
0000 0000 0000 0000 0000 0011 1111 1010 //不是是立即数,因为只有一个0
立即数计算
- step1:
我们先对当前的immediate
进行一个填充前置0使得总共的二进制位数为32位
- step2:
对当前的这个immediate
做一个循环右移(想想成一个环形,如果最低位右移,这个位置的值会移动到最高位去)
eg:
immediate:0000 0000 0000 0000 0000 0000 1111 0011
rotate :0010
我们将immediate循环右移4次:
该立即数为:0011 0000 0000 0000 0000 0000 0000 1111 (和上面对比就是将低位的四位移动到高位的前四位去了)
CPU中断处理过程
- 中断请求发生后,CPU判断该中断请求是否屏蔽,若未屏蔽则进入中断响应状态;
- 中断响应状态进入中断服务处理部分,此部分需要完成保护现场的功能。
- 中断处理部分执行完成后,进入中断返回,此部分需要恢复现场。
NVIC的特征
- 支持嵌套和向量中断
- 自动保存和恢复处理器状态
- 动态改变优先级
编程题
Q1:
假设发光二极管使用的是GPIOE口的4,5,6引脚,给定延时函数为 Delay_ms()
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
使用方法,循环点亮LED代码
void led_init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
// 第5引脚,配置为推挽输出功能,工作频率为2MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
// 对GPIO_B.5和GPIO_E.5进行上述配置
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_Init(GPIOE, &GPIO_InitStructure);
// 初始化LED为灭
GPIO_SetBits(GPIOB, GPIO_Pin_5);
GPIO_SetBits(GPIOE, GPIO_Pin_5);
}
void set_led(LED_ID_TypeDef led_id, LED_TypeDef status) {
void (*GPIO_status[2])(GPIO_TypeDef*, uint16_t) = {GPIO_SetBits, GPIO_ResetBits};
if (led_id == DS0)
GPIO_status[status](GPIOB, GPIO_Pin_5);
if (led_id == DS1)
GPIO_status[status](GPIOE, GPIO_Pin_5);
}
void slove(){
NVIC_SetPriorityGrouping(NVIC_PriorityGroup_2);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE, ENABLE);
led_init();
while (1) {
set_led(DS1, OFF);
delay_ms(1000);
set_led(DS1, ON);
delay_ms(1000);
}
}
串口初始化
void uart_init(u32 bound) {
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
// 0. 开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
// 1.1 配置PA9为TX功能
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 1.2 配置PA10为RX功能
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 2. 初始化串口工作模式
USART_InitStruct.USART_BaudRate = bound;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x2;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x2;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
USART_ITConfig(USART1,USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
}
二进制处理
后续更新吧
版权声明:本文为CSDN博主「MangataTS」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_46201544/article/details/122047355
暂无评论