stm32为什么给有些寄存器赋值确不会影响其他位?USARTx->SR = (uint16_t)~USART_FLAG

本文介绍了STM32微控制器中寄存器的不同类型及其操作方式,解释了为何某些寄存器可以直接赋值而不会影响其他位,并列举了各种寄存器的属性和操作规则。

新手小白可能会遇到的问题:stm32为什么给有些寄存器赋值确不会影响其他位?在stm32的库函数中可以看到有的关于位的操作不是用位与位或,而是直接赋值,但确不会影响其他位,例如:USARTx->SR = (uint16_t)~USART_FLAG,原因在于sr寄存器只能硬件置1,软件写1无效,关于这些寄存器的错作细则可以在stm32的手册中查询,

在对寄存器的描述中使用了下列缩写:
read / write (rw)
软件能读写此位。
read-only (r)
软件只能读此位。
write-only (w)
软件只能写此位,读此位将返回复位值。
read/clear (rc_w1)
软件可以读此位,也可以通过写’1’清除此位,写’0’对此位无影响。
read / clear (rc_w0)
软件可以读此位,也可以通过写’0’清除此位,写’1’对此位无影响。
read / clear by read (rc_r)
软件可以读此位;读此位将自动地清除它为’0’,写’0’对此位无影响。
read / set (rs)
软件可以读也可以设置此位,写’0’对此位无影响。
read-only write trigger (rt_w)
软件可以读此位;写’0’或’1’触发一个事件但对此位数值没有影响。
toggle (t)
软件只能通过写’1’来翻转此位,写’0’对此位无影响。
Reserved(Res.)
保留位,必须保持默认值不变

在查看寄存器时会看到这些标志,我们根据这些标志就可以知道怎么对寄存器操作了~

#include "usart.h" #if USART1_ENABLE uint8_t usart1SendBuf[USART_SEND_BUF_SIZE+1]; uint8_t usart1RecvBuf[USART_RECV_BUF_SIZE+1]; RingBufferTypeDef usart1SendRingBuf; RingBufferTypeDef usart1RecvRingBuf; Usart_DataTypeDef usart1; #endif #if USART2_ENABLE uint8_t usart2SendBuf[USART_SEND_BUF_SIZE+1]; uint8_t usart2RecvBuf[USART_RECV_BUF_SIZE+1]; RingBufferTypeDef usart2SendRingBuf; RingBufferTypeDef usart2RecvRingBuf; Usart_DataTypeDef usart2; #endif #if USART3_ENABLE uint8_t usart3SendBuf[USART_SEND_BUF_SIZE+1]; uint8_t usart3RecvBuf[USART_RECV_BUF_SIZE+1]; RingBufferTypeDef usart3SendRingBuf; RingBufferTypeDef usart3RecvRingBuf; Usart_DataTypeDef usart3; #endif void Usart_Init(void) { //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; // 串口配置结构体 USART_InitTypeDef USART_InitStructure; // 外部中断结构体 NVIC_InitTypeDef NVIC_InitStructure; #if USART1_ENABLE // 赋值结构体usart指针 usart1.pUSARTx = USART1; // 初始化缓冲区(环形队列) RingBuffer_Init(&usart1SendRingBuf, USART_SEND_BUF_SIZE, usart1SendBuf); RingBuffer_Init(&usart1RecvRingBuf, USART_RECV_BUF_SIZE, usart1RecvBuf); usart1.recvBuf = &usart1RecvRingBuf; usart1.sendBuf = &usart1SendRingBuf; // usart1.recvBuf = RingBuffer_Init(USART_RECV_BUF_SIZE); // usart1.sendBuf = RingBuffer_Init(USART_SEND_BUF_SIZE); // 使能USART时钟 USART1_APBxClkCmd(USART1_CLK, ENABLE); // 使能GPIO时钟 USART1_GPIO_APBxClkCmd(USART1_GPIO_CLK, ENABLE); // 配置串口USART的发送管脚 GPIO_InitStructure.GPIO_Pin = USART1_TX_GPIO_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(USART1_TX_GPIO_PORT, &GPIO_InitStructure); // 配置串口USART的接收管脚 GPIO_InitStructure.GPIO_Pin = USART1_RX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(USART1_RX_GPIO_PORT, &GPIO_InitStructure); //USART 初始化设置 USART_InitStructure.USART_BaudRate = USART1_BAUDRATE;//串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8数据格式 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; //收发模式 // NVIC 配置串口外部中断 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 嵌套向量中断控制器组选择 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器 // 初始化串口 USART_Init(USART1, &USART_InitStructure); //开启串口接收中断 IT: Interupt USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 使能串口 USART_Cmd(USART1, ENABLE); #endif #if USART2_ENABLE // 赋值结构体usart指针 usart2.pUSARTx = USART2; // 初始化缓冲区(环形队列) RingBuffer_Init(&usart2SendRingBuf, USART_SEND_BUF_SIZE, usart2SendBuf); RingBuffer_Init(&usart2RecvRingBuf, USART_RECV_BUF_SIZE, usart2RecvBuf); usart2.recvBuf = &usart2RecvRingBuf; usart2.sendBuf = &usart2SendRingBuf; // 使能USART时钟 USART2_APBxClkCmd(USART2_CLK, ENABLE); // 使能GPIO时钟 USART2_GPIO_APBxClkCmd(USART2_GPIO_CLK, ENABLE); // 配置串口USART的发送管脚 TX GPIO_InitStructure.GPIO_Pin = USART2_TX_GPIO_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(USART2_TX_GPIO_PORT, &GPIO_InitStructure); // 配置串口USART的接收管脚 RX GPIO_InitStructure.GPIO_Pin = USART2_RX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(USART2_RX_GPIO_PORT, &GPIO_InitStructure); // Usar21 NVIC 配置串口外部中断 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器 //USART 初始化设置 USART_InitStructure.USART_BaudRate = USART2_BAUDRATE;//串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8数据格式 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(USART2, &USART_InitStructure); //开启串口接收中断 IT: Interupt USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); // 使能串口 USART_Cmd(USART2, ENABLE); #endif #if USART3_ENABLE // 赋值结构体usart指针 usart3.pUSARTx = USART3; // 初始化缓冲区(环形队列) RingBuffer_Init(&usart3SendRingBuf, USART_SEND_BUF_SIZE, usart3SendBuf); RingBuffer_Init(&usart3RecvRingBuf, USART_RECV_BUF_SIZE, usart3RecvBuf); usart3.recvBuf = &usart3RecvRingBuf; usart3.sendBuf = &usart3SendRingBuf; // 使能USART时钟 USART3_APBxClkCmd(USART3_CLK, ENABLE); // 使能GPIO时钟 USART3_GPIO_APBxClkCmd(USART3_GPIO_CLK, ENABLE); // 配置串口USART的发送管脚 TX GPIO_InitStructure.GPIO_Pin = USART3_TX_GPIO_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(USART3_TX_GPIO_PORT, &GPIO_InitStructure); // 配置串口USART的接收管脚 RX GPIO_InitStructure.GPIO_Pin = USART3_RX_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(USART3_RX_GPIO_PORT, &GPIO_InitStructure); // Usart NVIC 配置串口外部中断 NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器 //USART 初始化设置 USART_InitStructure.USART_BaudRate = USART3_BAUDRATE;//串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8数据格式 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(USART3, &USART_InitStructure); //开启串口接收中断 IT: Interupt USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // 使能串口 USART_Cmd(USART3, ENABLE); #endif } /* 发送单个字节 */ void Usart_SendByte(USART_TypeDef *pUSARTx, uint8_t ch) { /* 发送一个字节到USART */ USART_SendData(pUSARTx, ch); /* 等待发送寄存器为空 */ while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } /* 发送8的字节流 */ void Usart_SendByteArr(USART_TypeDef *pUSARTx, uint8_t *byteArr, uint16_t size){ uint16_t bidx; for (bidx=0; bidx<size; bidx++){ Usart_SendByte(pUSARTx, byteArr[bidx]); } /* 等待发送寄存器为空 */ // while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } /* 发送字符串 */ void Usart_SendString(USART_TypeDef *pUSARTx, char *str){ uint16_t sidx=0; do { Usart_SendByte(pUSARTx, (uint8_t)(*(str + sidx))); sidx++; } while(*(str + sidx) != '\0'); /* 等待发送寄存器为空 */ // USART_FLAG_TXE: Transmit data register empty flag 发送数据寄存器为空 // RESET = 0 // SET = 1 // while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } // 将串口发送缓冲区的内容全部发出去 void Usart_SendAll(Usart_DataTypeDef *usart){ uint8_t value; while(RingBuffer_GetByteUsed(usart->sendBuf)){ value = RingBuffer_Pop(usart->sendBuf); // printf("Usart_SendAll pop: %d", value); Usart_SendByte(usart->pUSARTx, value); } } #if USART1_ENABLE // 定义串口中断处理函数 void USART1_IRQHandler(void){ uint8_t ucTemp; if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) { // 从串口读取一个字符 ucTemp = USART_ReceiveData(USART1); // 新的字符添加到串口的环形缓冲队列中 RingBuffer_Push(usart1.recvBuf, ucTemp); } } // 重定向c函数printf到串口,重定向后可使用printf函数 // int fputc(int ch, FILE *f) //{ // while((USART1->SR&0X40)==0){} // /* 发送一个字节数据到串口 */ // USART_SendData(USART1, (uint8_t) ch); // /* 等待发送完毕 */ // // while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET); // return (ch); //} // 重定向c函数scanf到串口,重向后可使用scanf、getchar等函数 // int fgetc(FILE *f) //{ // /* 等待串口输入数据 */ // while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET); // // return (int)USART_ReceiveData(USART1); // } #endif #if USART2_ENABLE // 定义串口中断处理函数 void USART2_IRQHandler(void){ uint8_t ucTemp; if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET) { // 从串口读取一个字符 ucTemp = USART_ReceiveData(usart2.pUSARTx); // 新的字符添加到串口的环形缓冲队列中 RingBuffer_Push(usart2.recvBuf, ucTemp); } } #endif #if USART3_ENABLE void USART3_IRQHandler(void){ uint8_t ucTemp; if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET) { // 从串口读取一个字符 ucTemp = USART_ReceiveData(usart3.pUSARTx); // 新的字符添加到串口的环形缓冲队列中 RingBuffer_Push(usart3.recvBuf, ucTemp); } } #endif 解释一下
07-17
#include "stm32f10x.h" // Device header #include <stdbool.h> #include <stdio.h> volatile uint8_t rxdata=0;//这种跨中断和应用程序的代码非常建议用volatile去优化,volatile表示这一个变量不接受任何优化,他的任何操作都必须经过内存去进行读,而不进行寄存器缓存 int main(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9 | GPIO_Pin_10 ; GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); USART_InitTypeDef USART_InitStructure; USART_StructInit(&USART_InitStructure); USART_InitStructure.USART_BaudRate=115200 ; USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None ; USART_InitStructure.USART_Mode= USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_Parity= USART_Parity_No; USART_InitStructure.USART_StopBits=USART_StopBits_1 ; USART_InitStructure.USART_WordLength=USART_WordLength_8b ; USART_Init(USART1,&USART_InitStructure); USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); USART_Cmd(USART1,ENABLE); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel= USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 5; NVIC_InitStructure.NVIC_IRQChannelSubPriority=0 ; NVIC_Init(&NVIC_InitStructure); char msg[64]; while(1) { if(rxdata!=0) { // sprintf(msg,"received:%c",(char)rxdata); //把一个字符串内容打印到msg里面去 int len=snprintf(msg, sizeof(msg), "received:%c\r\n", (char)rxdata);//用起来比上面更安全 for(int i=0;i<len;i++) { while(!USART_GetFlagStatus(USART1,USART_FLAG_TXE)) USART_SendData(USART1,(uint16_t) msg[i]); } rxdata=0; } } } void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET) { rxdata=USART_ReceiveData(USART1); USART_ClearITPendingBit(USART1,USART_IT_RXNE);//关了(USART1,USART_IT_RXNE)这个中断 } }
最新发布
11-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值