今天主要是加深了对串口的理解,还有一些和小组成员调试电路的心得
串口部分:
这里就正点原子的库函数中的例子,来说说我现在的理解
void uart_init(u32 bound){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
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(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART1, ENABLE); //使能串口1
}
首先就是GPIO、串口、NVIC这些的结构体定义,开启时钟。
因为这里用到串口一,根据正点原子内定的引脚分布,这里就是初始化PA9和PA10作为发送和接收引脚、浮空输入还有推挽复用输出、速率配置就是快一点好、最后用Init初始化这俩个引脚。
这里NVIC的配置,我其实就是看着代码可以理解。细节的话,等我下次复习中断的时候细讲一下
来说说这个串口的配置:
串口波特率:这个我简单的理解还是每秒钟发送bit的个数,比如我一般配置115200,就是每秒钟发送115200个bit(我发现对波特率和比特率还是要再看看)
字长:这里设定的是8位,这个是传输有效数据的位数,不是一帧数据的位数,比如我现在要传输5,转化成过去就应该是0000 0101。这里是不包括起始位和要配置的结束位,奇偶校验位这些的。
结束位和奇偶校验位:这俩个就是自己看要不要配置,或者传输过程中自己需要不需要这些数据来帮助自己观察(我这里就是很简单的数据传输,就加一个结束位)
硬件流控制:这个我看了好多代码,也都没有用上,所以我也不懂。
模式设定:因为我这次要发送数据也要接收数据,所以就是Rx和Tx俩种模式。
初始化、开启中断、使能。
这里面我觉得有必要问问:为什么中间选用的是USART_IT_RXNE,而不是其他的?是不是外设初始化了都还要使能呢?那为什么GPIO不用呢?
这些问题,我觉得要答得上来才可以说看了一遍这个代码。
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1); //读取接收到的数据
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
else USART_RX_STA|=0x8000; //接收完成了
}
else //还没收到0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
(今天我其实花了很多的时候在填之前看没这个中断服务助手的坑)
这里我想想说说我自己的理解:回车换行、标志位的设定
这里判断是不是发送过来一帧数据,是通过回车换行的ASCII码(0x0D 0x0A)来判定的。如果是的话,就用位与的操作将第15位置一跳出循环。主函数中通过判断第15位,来读取信息;如果不是相对于的ASCII码,那就一直从usart->dr中读取数据(当然这里也是有限定的:读取的最大信息长度限定)。
这个其实就是规定了一个通信接收协议,通过帧尾来判断是否传输一帧数据过来,然后显示出来。
这里,也有一个问题要问问:
为什么这个中断服务助手中不用将标志位置零?这样会不会导致一直读取一个数据,一直卡在这个中断服务助手里面呢?
答案就自己去找咯。
白天差不多看个大概这个串口之后,我就尝试和串口屏进行通信。
if(USART_RX_STA & 0x8000)
{
len = USART_RX_STA&0x3fff;
if(USART_RX_BUF[0]==0x03 && USART_RX_BUF[1] == 0x03 && USART_RX_BUF[2] == 0 && USART_RX_BUF[3] == 0)
{
LED1 = !LED1;
USART_RX_STA = 0;
}
}
printf("data.n0.val=100\xff\xff\xff");
printf("data.n1.val=200\xff\xff\xff");
printf("data.n2.val=300\xff\xff\xff");
LED0 = !LED0;
delay_ms(1000);
delay_ms(1000);
我发现,print真的是一个很厉害的重定义函数,这个后面我想好好看看这个函数到底是怎么用的
这里就是理解成,把指定的数据通过串口引脚输出,就比如这里的“data.n0.val=100\xff\xff\xff”
因为我用的陶晶驰的串口屏,所以这个其实就是相对应的语法了,后面的xff就是串口屏通信协议中的结束标志位。
上面的if判断是用来接收串口屏发送过来的数据是不是满足要求,这个输出的语法,我也很想学学,感觉很好玩,就是掌握这些通信的内部规矩之类的。
综上:
串口就是用来通信一个外设,有自己的通信协议、也可以自己规定通信协议。其中的细节需要自己用的时候去理解。
(今天搞明白很多之前没搞明白的东西,真的让我有了很多信心)
电路调试:
因为我们这次做的题目是19年的D题:信号装置测试仪器
说句实话,我们之前在分析这道题目的时候,理论都走得通(就是基本的模电知识),哪怕像后面的发挥部分,我也觉得挺简单的,无非就是根据之前测出来的数据一点点排查过去。
但是真的启用电路的时候,发现没有那么简单。
首先就一个输入电阻的测量:
我们用的电流等效,在Rin前面加一个标称电阻来计算。这里单片机一接入引脚,就会直接对波形和幅度产生影响;我们是根据前后接入的数值来加减排除噪声源,这才排除了单片机接入的影响;然后测量指标并不是那么线性的,我们按照题目要求改变元器件,发现这个实际电路的变化和理论值完全是不一样的,我们在测量输入电阻部分就是花了很大心思(排除噪声源、元器件本身带来的影响……)
接着测量输出电阻:
好家伙,单片机一接入输出部分的电路,甚至会对输入电阻产生影响!!!
这里我们就重新拟合了一遍数据。
然后我们加入选通开关4051 还有 有效值检波、继电器SRD,又在一遍遍排除影响和拟合数据。
……
听着挺丧的,但是我觉得很有意思和好玩。
说说我觉得好玩的点和有意思的点:
我一直都知道理论指导实践,理论要想完全落地是很难的。但是我不知道这个度到底是一个什么样的?究竟这个难度是咋样的呢?究竟会卡在什么地方?要怎么去解决这些问题呢?
就举今天晚上的例子来说:
1.我们光就排除噪声源这个小点,是想了很久才知道直接对数据进行偏差出来才解决的
(想法一时没有、落地挺简单)
2.联调数据偏差很大,需要重新处理
(挺打击硬件的同学、相当于之前测量的都没有用、考验心性)
3.从理论的角度分析这些问题到底是出在什么地方?
(刨析问题本质的能力)
我觉得很容易会被这些表象给困惑住,因为一个整体出不来结果,就是很容易让人无处下手、灰心
但是,转念一想,这不正是联调要做的事情吗?这不才是考验到底具备不具备这些能力的最好时机吗?
所以,我觉得这些很好玩很有意思。