单片机需要做的工作:
1.和ADC芯片通讯,读取AD值,并根据AD值计算成电阻值;
2.参数校准,通过USART1和上位机通讯,走MODBUS协议;
3.和主设备通讯,通过SPI2和主设备通讯,自定义协议。
其中2是产品出厂前调试用的,单片机正常工作情况下,就是读取ADC值,并传给主设备。
分开说。
1.和ADC芯片通讯也是走的SPI,用的是单片机的SPI1,单片机作为主设备。工作方式是这样的,单片机发送条指令,ADC芯片开始采样,采样过程需要一定时间,采样接收后将SPI的MISO引脚拉低通知单片机可以读取数据。单片机再发送SPI命令读取ADC值。然后单片机开始根据设定好的参数将ADC值转化成电阻值。
2.上一步将ADC值计算成电阻值的过程用到的参数,是通过上位机设定的。通过USART1和上位机通讯,走标准MODBUS协议。从网上搜了个STM32用的MODBUS协议,感觉还可以。
3.第一步计算出来的电阻值,最好是要传给主设备的。通过SPI2和主设备相连,我现在做的这个板做SPI从设备。主设备不停的发送SPI读取命令,于是我想用SPI的DMA功能实现。
---------------------------------------
因为一开始是想一步做一步的,功能一点一点的加进来,结果现在的流程很混乱。
于是想写下来理一理。
while(1)
{
if(Comu_Busy == 0) //USART1没有接收到据,处于工作状态1或工作状态3
switch(ad7193DataFlag) //根据ad7193DataFlag标志,判断工作情况
{
case 0x00: //发送adc读取命令,等待adc采样
...
ad7193DataFlag = 1;
break;
case 0x01: //根据上一次读取的adc值计算电阻值
...
ad7193DataFlag = 2;
break;
case 0x02: //读取adc值或等待
if(spi1_miso == 0)
{
...
ad7193DataFlag = 0; //读取spi1_miso状态,如果是低电平,开始读取adc值,然后ad7193DataFlag清零
} //如果spi1_miso是高电平,则ad7193DataFlag仍保持2,继续等待
break;
}
}
因为发送命令到采样完成可被读取,中间需要一定时间,故在这段时间内计算上次读取的adc值,转化为电阻值。
现在加进去的部分是和主设备的spi通讯部分,用的是spi2,作为从设备,接收用中断,发送用DMA。
现在的尝试是,在上面程序部分的case 0x01里,adc值转化为电阻值后,开启spi2中断,然后在spi2中断函数里,判断帧首,如果接收的数据是帧首,则置个标志,开始接收帧的其他数据,帧长度有限,5个16位数据。如果接受的数据超过5个,则关断spi2中断并置个标志。如果第一个接收的数据不是帧首,也是关断spi2中断。
void SPI2_IRQHandler(void)
{
spi2Temp = SPI_I2S_ReceiveData(SPI2);
if(spi2Num == 0) //接收数组未保存任何数据
{
if(spi2Temp == 0x3a05) //如果数据是帧首
{
spi2Num = 1;
spi2Recive[0] = spi2Temp;
}
else
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, DISABLE);
}
else //已经接收过帧首
{
spi2Recive[spi2Num] = spi2Temp; //保存剩下帧
spi2Num++;
if(spi2Num > 4) //如果超过5个数据
{
spi2Num = 0;
spi2ReciveOk = 1;
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, DISABLE);
}
}
else
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, DISABLE);
}
现在在修改spi2部分,思维好乱。
之前只读取spi2接收到的5个数据,只判断帧首,然后通过串口发上来,貌似可以。
现在又加进来帧尾的CRC判断,又加了几个标志,然后就不正常了,我脑子也乱了...
|