不要轻易说不可以--10_03_20

挑战极限:嵌入式项目的迭代之路
本文回顾了一个嵌入式项目的迭代历程,从最初的ARM Cortex-M3 MCU选择到应对成本压力时采用8051核SOC的挑战,再到不断优化算法以满足客户的新需求。项目团队通过不懈努力,成功地将产品性能与成本平衡至最优。

----如果要证明它行,你只需要证明它不行!

 ----你能成为千万富翁,不能?那么请证明给我看你不能,仅此而已。

 

------------------------------------

 

跟一个项目有两年了,按照客户需求也不知道改了多少版程序,性能也在逐步提高,早早的超过了客户的预期,可因为商务上的一些事情,客户始终没有下订单,但是我们都知道我们还得继续按照客户的要求去改.....继续跟下去...现在只是简单的回顾下这个历程吧。

两年前,在没有客户需求的情况下,我们自己提出了一个技术项目,也定了自己的目标。最开始选用的是基于ARM Cortex-M3的一款MCU,主要注重在性能,可靠性,实时性等等方面力求做到最好。这个目标也实现了,与市场上同类产品比较起来,性能有明显提高。 当我们市场带着这款样品出去推的时候,也得到了客户的好评与认可,并提出了新的需求。

 

 

在新需求下,成本有相当压力,于是开始省钱,硬件上从电容省起,甚至将必要的时钟晶体都省略了一个,硬件组的同事辛苦了。而对软件来说,我们选用了 一个新的平台,一款含有8051核的SOC,现在还清醒的记得,我的第一反应是不行,开什么玩笑。呵呵,虽然觉得不行但是还是要出文档去证明它不行,经过 一个月的评估,利用汇编重写了大量的C函数,充分布局RAM空间,结论是可以试试。于是2个月过后,我们成功的在该SOC上实现了原来产品的功能,性能上 虽然没有明显提高,但是成本上却下降了不少。回过头去看这件事,我们将SOC的RAM空间每个字节都进行了定义,而最后只有一个字节是空闲的。这件事情 上,我们都觉得已经将SOC的性能发挥到了极致,事实上,SOC原厂的人也说了,他们可以在datasheet上多写一条该SOC的应用场景了。

 

 

我们都以为这个项目到这个程度,可以说是趋于完美了,可客户有了新的需求,也就是打算用性能去换取成本,即使我们的成本比他原有方案已经降低了不 少。于是开始使用新的算法,新的需求,新的软件架构.....行不行,又得评估,开始重写C算法核心对应的汇编程序,第一次测出的结果是超过要求的 100%,不行,于是开会讨论优化,从C算法优化开始,一直到汇编,测试超过预期40%,不行,汇编语句逐条逐条推敲,省略所有子函数的调用,全部采用内 联方式,充分利用该SOC硬件特性,力求将MCU与外设并行处理做到最大化...对照指令表,一个指令周期一个指令周期的省..最后达到预期。这一次,我 们都学乖了,没有人再说使SOC的应用达到极致了.....

 

 

所以啊,哥,不要轻易说不可能,你去证明不可能的时候要竭尽全力去让他变为可能,最后它就可能了。

/** ****************************************************************************** * @file PWR_STOP/main.c * @author MCD Application Team * @version V1.0.1 * @date 11-October-2013 * @brief Main program body ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2> * * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "MM32F031xxn.h" #include <math.h> //Library #include "user.h" #include "control_circuit.h" //函数声明 void on_off(uint8_t num); void uart2_report(void); void uart1_communication(void); void report2_format(void); void auto2_sending(void); void Delay_Ms(uint32_t time_ms); //变量声明 uint32_t counter_cycle, uart1_rate, uart2_rate, cntr_unse, cntr_tim14; uint16_t adc_v, voltage, o2c, o2f, o2t, o2RH, o2P; uint32_t o2p, kpa; uint8_t USART1_TXbuffer[30], USART1_RXbuffer[30], USART2_TXbuffer[30], USART2_RXbuffer[30], buf_us6300[4], report8[30]; u8 flag_pad, flag_menu, flag_light, battery, display_flag; uint16_t voltage_buffer[15], power_off_cntr; uint8_t rx_flag, code_right, code_num, flag_adj, flash_write; uint8_t USART1_RXtotal, USART1_TXtotal, USART2_RXtotal, USART2_TXtotal, flag_preparing_report, sensor_num; float o2c_factor, o2f_factor, atm, temperature; uint8_t I2C1_Tx_Buffer[16]; uint8_t I2C1_Rx_Buffer[16]; //void data_init(void) //{ // STMFLASH_Read (FLASH_STORE_BASE_ADDR,(uint8_t*)I2C1_Rx_Buffer,16); // if((I2C1_Rx_Buffer[0]==0xAA)&&(I2C1_Rx_Buffer[3]==0x55)) // { // o2c_add = I2C1_Rx_Buffer[1]; // o2f_add = I2C1_Rx_Buffer[2]; // } // else // { // I2C1_Tx_Buffer[0] = 0xAA; // I2C1_Tx_Buffer[1] = o2c_add; // I2C1_Tx_Buffer[2] = o2f_add; // I2C1_Tx_Buffer[3] = 0x55; // STMFLASH_Write(FLASH_STORE_BASE_ADDR,(uint8_t*)I2C1_Tx_Buffer,16); // } // if(o2f_add>0x80) // o2f_factor = 1 + 0.01*(o2f_add - 0x80); // else // o2f_factor = 1 - 0.01*(0x80-o2f_add); //} int main(void) { GPIO_InitTypeDef GPIO_InitStructure; uint32_t i; uint8_t enable; for (i=0;i<MILLISECOND*64*10;i++){} // 这段延时可省去: // ------初始化全局变量------------ o2c = 210; o2f = 0; sensor_num = 0; flag_menu = 0; flash_write = 0; stm32_Init (); uart1_communication(); uart2_report(); ControlCircuit_Init(); // 初始化12V控制IO // data_init(); LED_ON; for (i=0;i<MILLISECOND*64*10;i++){} // 这段延时可省去: LED_OFF; VAL_ON; // 开启12V输出 Voltage12V_Control(1); // 关闭12V输出 //Voltage12V_Control(0); // I2CInitMasterMode(); // I2CMasterWrite(I2C1,US6300_ADDR, 0x06, 0, buf_us6300); for (i=0;i<500000;i++){}; // 这段延时可导致标定时通信正常;但有时,在线仿真时没有此延时,EEPROM无法通过; // I2CMasterWrite(I2C1,US6300_ADDR, 0x50, 0, buf_us6300); // for (i=0;i<500;i++){}; // I2CMasterWrite(I2C1,US6300_ADDR, 0x30, 0, buf_us6300); // for (i=0;i<500;i++){}; // I2CMasterWrite(I2C1,US6300_ADDR, 0xAA, 0, buf_us6300); // for (i=0;i<500000;i++){} // 这段延时可导致标定时通信正常;但有时,在线仿真时没有此延时,EEPROM无法通过; // IWDG->KR = 0xAAAA; // 刷新看门狗IWDG ;写入0xAAAA=装入重载值; IWDG->KR = 0xCCCC; // 启动看门狗; IWDG->KR = 0xAAAA; // 刷新看门狗IWDG; 写入0xAAAA=装入重载值; // I2CMasterWrite(I2C1,US6300_ADDR, 0xAA, 0, buf_us6300);//读第一次数据时必须唤醒3次 // for (i=0;i<500000;i++){} // 这段延时可导致标定时通信正常;但有时,在线仿真时没有此延时,EEPROM无法通过; // IWDG->KR = 0xAAAA; // 刷新看门狗IWDG ;写入0xAAAA=装入重载值; // ***************************************************** while(1) { IWDG->KR = 0xAAAA; // 刷新看门狗IWDG ;写入0xAAAA=装入重载值? if(flag_menu) { // I2CMasterWrite(I2C1,US6300_ADDR, 0x50, 0, buf_us6300); // for (i=0;i<5000;i++){}; // I2CMasterWrite(I2C1,US6300_ADDR, 0x50, 0, buf_us6300); // for (i=0;i<5000;i++){}; // I2CMasterWrite(I2C1,US6300_ADDR, 0x30, 0, buf_us6300); // for (i=0;i<5000;i++){}; // I2CMasterRead1_6300(I2C1,US6300_ADDR, 3, buf_us6300); // atm = ((buf_us6300[0]&0x0f)*256*256 + buf_us6300[1]*256 + buf_us6300[2])/1000.0; //value/10=hpa,kpa/6.895=psi,hpa/6.895=psi*10; // for (i=0;i<5000;i++){}; // I2CMasterWrite(I2C1,US6300_ADDR, 0x32, 0, buf_us6300); //温度 // for (i=0;i<5000;i++){}; // I2CMasterRead1_6300(I2C1,US6300_ADDR, 3, buf_us6300); // temperature = ((buf_us6300[0]&0x0f)*256*256 + buf_us6300[1]*256 + buf_us6300[2])/100.0; flag_menu = 0; } } } // ***************************************************************************************** // 准备常规报 // ***************************************************************************************** void report2_format(void) { uint32_t i,j; uint8_t temp, temp_AAA[4], temp2_AAA[20]; uint16_t temp_u16; uint32_t temp_u32; union AAA { float f[5] ; u8 u8_[20]; } convert; // convert.f[0] = (float)o2c/10; convert.f[1] = (float)o2RH/10; convert.f[2] = (float)o2t/10; //--传感器显示此数据 convert.f[3] = (float)o2P/10; convert.f[4] = (float)atm; for (i=0;i<5;i++) //5个浮点 { for (j=0;j<4;j++) temp_AAA[3-j] = convert.u8_[i*4+j]; for (j=0;j<4;j++) temp2_AAA[i*4+j] = temp_AAA[j]; } flag_preparing_report=1; //防止在变更过程中发送 for (i=0;i<20;i++) report8[i+4] = temp2_AAA[i]; //利用union将浮点转到report8中; report8[0]=0x16; report8[1]=0x09; report8[2]=0x01; report8[3]=sensor_num-1; temp = 0; for(i=0;i<24;i++) temp += report8[i]; report8[24] = 0x00 - temp; //计算校验字; for (i=0;i<25;i++) USART2_TXbuffer[i] = report8[i]; //将report8拷贝; report8[i] flag_preparing_report = 0; } // ******************************************************************************* // auto_sending自动发送浓度 // ******************************************************************************* void auto2_sending(void) //正常检测时,自动发送检测数据----复核时模式应该还是calibration, 符合完成后才改成NORMAL; { if(flag_preparing_report==0) //防护措施:防止数据准备未完成时发送; { DMA_Cmd(DMA1_Channel4, DISABLE); DMA1_Channel4->CMAR = (u32)&USART2_TXbuffer; DMA1_Channel4->CNDTR = USART2_TXtotal; //DMA通道的DMA缓存的大小 DMA_Cmd(DMA1_Channel4, ENABLE); } } void uart1_communication(void) { uint16_t temp_16; //GPIO端口设置 DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; UART_InitTypeDef UART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE); //使能UART2 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); //开启GPIOA时钟 //UART1 NVIC 配置 //UART 初始化设置 GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1); GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1); uart1_rate = 9600; UART_InitStructure.UART_BaudRate = uart1_rate;//串口波特率 USART1_TXtotal = 4; USART1_RXtotal = 12; UART_InitStructure.UART_WordLength = UART_WordLength_8b;//字长为8位数据格式 UART_InitStructure.UART_StopBits = UART_StopBits_1;//一个停止位 UART_InitStructure.UART_Parity = UART_Parity_No;//无奇偶校验位 UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;//无硬件数据流控制 UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx; //收发模式 UART_Init(UART1, &UART_InitStructure); //初始化串口1 UART_Cmd(UART1, ENABLE); //使能串口1 //UART1_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 //UART1_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 // printf("UART OK!\r\n"); //----------UART1_DMA配置部分------------------- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA1_Channel2); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(UART1->TDR); //DMA外设ADC基地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_TXbuffer; //DMA内存基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向,从内存读取发送到外设 DMA_InitStructure.DMA_BufferSize = USART1_TXtotal; //DMA通道的DMA缓存的大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为8位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输 DMA_Init(DMA1_Channel2, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道UART1_Tx_DMA_Channel所标识的寄存器 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) &(UART1->RDR); //DMA外设ADC基地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_RXbuffer; //DMA内存基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,赐馍栌读取发送到内存 DMA_InitStructure.DMA_BufferSize = USART1_RXtotal; //DMA通道的DMA缓存的大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为8位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Low; //DMA通道 x拥有中优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输 DMA_Init(DMA1_Channel3, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道UART1_Tx_DMA_Channel所标识的寄存器 NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE); // UART_DMACmd(UART1,UART_DMAReq_EN,ENABLE); //使能uart1 DMA DMA_ITConfig(DMA1_Channel3,DMA_IT_TC,ENABLE); UART_DMACmd(UART1,UART_DMAReq_EN,ENABLE); //使能uart1 DMA // DMA_Cmd(DMA1_Channel4, ENABLE); DMA_Cmd(DMA1_Channel3, ENABLE); } void uart2_report(void) { uint16_t temp_16; //GPIO端口设置 DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; UART_InitTypeDef UART_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART2, ENABLE); //使能UART2 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); //开启GPIOA时钟 //UART1 NVIC 配置 //UART 初始化设置 GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_1); GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_1); uart2_rate = 115200; UART_InitStructure.UART_BaudRate = uart2_rate;//串口波特率 USART2_TXtotal = 25; USART2_RXtotal = 8; UART_InitStructure.UART_WordLength = UART_WordLength_8b;//字长为8位数据格式 UART_InitStructure.UART_StopBits = UART_StopBits_1;//一个停止位 UART_InitStructure.UART_Parity = UART_Parity_No;//无奇偶校验位 UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;//无硬件数据流控制 UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx; //收发模式 UART_Init(UART2, &UART_InitStructure); //初始化串口1 UART_Cmd(UART2, ENABLE); //使能串口1 //UART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9 //UART1_RX GPIOA.10初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 // printf("UART OK!\r\n"); //----------UART1_DMA配置部分------------------- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); //使能DMA传输 DMA_DeInit(DMA1_Channel4); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(UART2->TDR); //DMA外设ADC基地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_TXbuffer; //DMA内存基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向,从内存读取发送到外设 DMA_InitStructure.DMA_BufferSize = USART2_TXtotal; //DMA通道的DMA缓存的大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为8位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输 DMA_Init(DMA1_Channel4, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道UART1_Tx_DMA_Channel所标识的寄存器 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) &(UART2->RDR); //DMA外设ADC基地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_RXbuffer; //DMA内存基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,赐馍栌读取发送到内存 DMA_InitStructure.DMA_BufferSize = USART2_RXtotal; //DMA通道的DMA缓存的大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为8位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Low; //DMA通道 x拥有中优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输 DMA_Init(DMA1_Channel5, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道UART1_Tx_DMA_Channel所标识的寄存器 NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE); // UART_DMACmd(UART1,UART_DMAReq_EN,ENABLE); //使能uart1 DMA DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE); UART_DMACmd(UART2,UART_DMAReq_EN,ENABLE); //使能uart1 DMA // DMA_Cmd(DMA1_Channel4, ENABLE); DMA_Cmd(DMA1_Channel5, ENABLE); } //** //矩阵切换 //** void on_off(uint8_t num) { uint8_t board, sensor_num; board = num%128/16; sensor_num = num%16; switch(board) //切换板编号 { case 0: EN0_ON; EN1_OFF; EN2_OFF; EN3_OFF; break; case 1: EN0_OFF; EN1_ON; EN2_OFF; EN3_OFF; break; case 2: EN0_OFF; EN1_OFF; EN2_ON; EN3_OFF; break; case 3: EN0_OFF; EN1_OFF; EN2_OFF; EN3_ON; break; } switch(sensor_num) //传感器编号 { case 15: A0_ON; A1_ON; A2_ON; A3_ON; break; case 14: A0_OFF; A1_ON; A2_ON; A3_ON; break; case 13: A0_ON; A1_OFF; A2_ON; A3_ON; break; case 12: A0_OFF; A1_OFF; A2_ON; A3_ON; break; case 11: A0_ON; A1_ON; A2_OFF; A3_ON; break; case 10: A0_OFF; A1_ON; A2_OFF; A3_ON; break; case 9: A0_ON; A1_OFF; A2_OFF; A3_ON; break; case 8: A0_OFF; A1_OFF; A2_OFF; A3_ON; break; case 7: A0_ON; A1_ON; A2_ON; A3_OFF; break; case 6: A0_OFF; A1_ON; A2_ON; A3_OFF; break; case 5: A0_ON; A1_OFF; A2_ON; A3_OFF; break; case 4: A0_OFF; A1_OFF; A2_ON; A3_OFF; break; case 3: A0_ON; A1_ON; A2_OFF; A3_OFF; break; case 2: A0_OFF; A1_ON; A2_OFF; A3_OFF; break; case 1: A0_ON; A1_OFF; A2_OFF; A3_OFF; break; case 0: A0_OFF; A1_OFF; A2_OFF; A3_OFF; break; } } //电压采样 void Get_Adc_Average(void) { uint8_t i; uint16_t temp_v, Temp_average_float; } //正常显示 void display(void) { } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t* file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* Infinite loop */ while (1) { } } #endif /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ #include "user.h" //------全局变量定义------- //------全局变量定义------- void I2C_Configuration(void); //void ADC_CH_DMA_Config(void); /*配置DMA4_5的中断*/ void NVIC_Config() { NVIC_InitTypeDef NVIC_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_5_IRQn;//DMA1_Channel4_5_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPriority = 0; NVIC_Init(&NVIC_InitStructure); } /*配置DMA4_5的中断*/ void Delay(uint32_t nCount) { while (nCount != 0) { nCount--; } } void uart_putc(unsigned char c) { while(!((UART1->ISR)&(1<<7))); UART1->TDR=c; } void uart_puts(char *s ) { while (*s) uart_putc(*s++); } void GPIO_INIT(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_11|GPIO_Pin_12; //PA6-背光脚、PA7-STB、PA12-喇叭控制 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_5; //PB0-CLK、PB1-DIO、PB5-LED GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); PVCC_ON; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4; //PB4-P_CS GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } /** * @brief Configures system clock after wake-up from STOP: enable HSE, PLL * and select PLL as system clock source. * @param None * @retval None */ void SYSCLKConfig_STOP(void) { /* After wake-up from STOP reconfigure the system clock */ /* Enable HSE */ RCC_HSEConfig(RCC_HSE_ON); /* Wait till HSE is ready */ while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET) {} /* Enable PLL */ RCC_PLLCmd(ENABLE); /* Wait till PLL is ready */ while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {} /* Select PLL as system clock source */ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */ while (RCC_GetSYSCLKSource() != 0x08) {} } //------------------------------------------------ //-----------------定时器配置--------------------- void stm32_TimerSetup (void) { //注意:TIMx中断轻易使能,因为如果TIMx已经启动,会自动引发中断,造成CPU无法跳到下一个断点;其中的原因还甚明了; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16, ENABLE ); //开启tim14时钟 TIM16->CR1 = 0; // reset command register 1 TIM16->PSC = 1000; // set prescaler;TIM3_CLK=72MHz/1=72MHz TIM16->ARR = 500*FCLK_H_MHZ-1; // 100uS TIM16->DIER |=1<<0; // enable interrupt NVIC_InitStructure.NVIC_IRQChannel = TIM16_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority =0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM16->CR1 |= 1<<0; // 启动timer2 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM14, ENABLE ); //开启tim17时钟 ---25ms TIM14->CR1 = 0; // reset command register 1 TIM14->PSC = 1000; // set prescaler;TIM3_CLK=72MHz/1=72MHz TIM14->ARR = 7*FCLK_H_MHZ-1; // 100uS TIM14->DIER |=1<<0; // enable interrupt NVIC_InitStructure.NVIC_IRQChannel = TIM14_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority =0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM14->CR1 |= 1<<0; // 启动timer2 } ///*---------------------------------------------------------------------------- // set HSI as SystemCoreClock (HSE is not populated on STM32L-Discovery board) // *----------------------------------------------------------------------------*/ void SystemCoreClockSetHSE(void) { RCC->CR |= ((uint32_t)RCC_CR_HSEON); /* Enable HSE */ while ((RCC->CR & RCC_CR_HSERDY) == 0); /* Wait for HSE Ready */ RCC->CFGR = RCC_CFGR_SW_HSE; /* HSE is system clock */ while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSE); /* Wait for HSE used as system clock */ // FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); // FLASH_SetLatency(FLASH_Latency_1); FLASH->ACR = FLASH_ACR_PRFTBE; /* Enable Prefetch Buffer */ FLASH->ACR |= FLASH_Latency_2; /* Flash 1 wait state */ RCC->CFGR |= RCC_CFGR_HPRE_DIV1; /* HCLK = SYSCLK */ RCC->CFGR |= RCC_CFGR_PPRE1_DIV1; /* PCLK = HCLK */ RCC->CFGR |= RCC_CFGR_PPRE2_DIV1; /* PCLK = HCLK */ RCC->CR &= ~RCC_CR_PLLON; /* Disable PLL */ /*PLL configuration: = HSE * 3 = 24 MHz */ // RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL); RCC->CFGR |=1<<16; RCC->CFGR &=~(1<<17); RCC->CR &=~(0x3f<<26); RCC->CR |=5 << 26; //设置PLL值 2~16 // RCC->CFGR |= (RCC_CFGR_PLLSRC_1 | RCC_CFGR_PLLMULL3); RCC->CR |= RCC_CR_PLLON; /* Enable PLL */ while((RCC->CR & RCC_CR_PLLRDY) == 0) __NOP(); /* Wait till PLL is ready */ RCC->CFGR &= ~RCC_CFGR_SW; /* Select PLL as system clock source */ RCC->CFGR |= RCC_CFGR_SW_PLL; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); /* Wait till PLL is system clock src */ // RCC->CR &= ~RCC_CR_HSION; /* Disable HSI /必须配置完成才能关闭内部时钟*/ } //---------------------------------------------------------------------------- // STM32 Independent watchdog setup. // initializes the IWDG register //---------------------------------------------------------------------------- void stm32_IwdgSetup (void) { RCC->CSR|= (1<<0); // LSI enable, necessary for IWDG while ((RCC->CSR& (1<<1)) == 0); // wait till LSI is ready IWDG->KR = 0x5555; //写入0x5555表示允许访问IWDG->PR, IWDG->RLR while ((IWDG->SR& (1<<0)) == 1); IWDG->PR = 4; //预分频系数:0=/4;1=/8;2=/16;3=/32;4=/64;5=/128;6=/256;7=/256 while ((IWDG->SR& (1<<1)) == 1); IWDG->RLR = 0xFFF; // 重载值(0-4095)=(超时周期*时钟频率-1)=; // 重载值= 3秒*128-1=383 IWDG->KR = 0xAAAA; // 写入0xAAAA=装入重载值; //IWDG->KR.all = 0xCCCC; // 启动看门狗; } // end of stm32_IwdgSetup /** * @brief ADC1 channel with DMA configuration * @param None * @retval None */ void ADC_CH_DMA_Config(void) { ADC_InitTypeDef ADC_InitStruct; DMA_InitTypeDef DMA_InitStruct; GPIO_InitTypeDef GPIO_InitStruct; /* ADC1 DeInit */ ADC_DeInit(ADC1);//主要功能:先使能ADC1时钟,再失能ADC1时钟 /* Enable GPIOA clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); /* Configure PA.01 as analog input */ GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN; //模拟输入和浮空输入 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); // PC1,输入时用设置速率 /* DMA1 clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE); /* DMA1 Channel1 Config */ DMA_DeInit(DMA1_Channel1); // DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;//stm32f030用 DMA_InitStruct.DMA_PeripheralBaseAddr = (u32)&(ADC1->ADDATA); DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&adc_v; DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStruct.DMA_BufferSize =1; DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;// /* ADC DMA request in circular mode */ DMA_InitStruct.DMA_Priority = DMA_Priority_High; DMA_InitStruct.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStruct); /* DMA1 Channel1 enable */ DMA_Cmd(DMA1_Channel1, ENABLE); /* Enable ADC_DMA */ ADC_DMACmd(ADC1, ENABLE); /* Initialize ADC structure */ ADC_StructInit(&ADC_InitStruct); /* ADC1 Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); /* Configure the ADC1 in continous mode withe a resolutuion equal to 12 bits */ ADC_InitStruct.ADC_PRESCARE = ADC_PCLK2_PRESCARE_2; ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b; ADC_InitStruct.ADC_Mode = ADC_Mode_Continuous_Scan; // ADC_InitStruct.ADC_TRGEN = ADC_TRG_Disable;//使用外部触发信号启动转换 ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; ADC_Init(ADC1, &ADC_InitStruct); /*屏蔽所有通道*/ ADC1->ADCHS&=0xffffffe00; /*使能选中通道,后面参数保留*/ ADC_RegularChannelConfig(ADC1, ADC_Channel_1 ,0 , ADC_SampleTime_13_5Cycles); // ADC_VrefintCmd(ENABLE); // ADC1->ADCFG|=0x04; 手册该位保留,必须为0; ADC_ExternalTrigConvCmd(ADC1,DISABLE); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); ADC_DMACmd(ADC1, ENABLE); /* Wait the ADCEN falg */ // while(!ADC_GetFlagStatus(ADC1, RESET)); /* ADC1 regular Software Start Conv */ ADC_SoftwareStartConvCmd(ADC1,ENABLE); } //------------------------------------------------------------------ // STM32 embedded Flash interface setup. // initializes the ACR register //------------------------------------------------------------------ void stm32_EfiSetup (void) { // u32 temp; FLASH->ACR = 0x00000012; // set access control register;__EFI_ACR_Val=0x00000012 FLASH->ACR|= 2<<0; //0=SYSCLK<24Mhz,1=<24<SYSCLK<48Mhz,2=48<SYSCLK<72Mhz; // temp= FLASH->ACR.all; } //external interrupt initialprocedure void EXTIX_Init(void) { EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);//外部中断,需要使能AFIO时钟 // SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource3); // // EXTI_InitStructure.EXTI_Line=EXTI_Line3; // EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发 // EXTI_InitStructure.EXTI_LineCmd = ENABLE; // EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource11); EXTI_InitStructure.EXTI_Line=EXTI_Line11; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource15); EXTI_InitStructure.EXTI_Line=EXTI_Line15; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 NVIC_InitStructure.NVIC_IRQChannel = EXTI4_15_IRQn; //使能按键所在的外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPriority = 0x02; //子优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 // NVIC_InitStructure.NVIC_IRQChannel = EXTI2_3_IRQn; //使能按键所在的外部中断通道 // NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01; //子优先级1 // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 // NVIC_Init(&NVIC_InitStructure); } void stm32_Init () { // stm32_EfiSetup(); //已经在MM32F031系统时钟配置中配置过 SystemCoreClockSetHSE(); //SYSTICK_INIT(); //SYSTICK一定要谨慎使用,用好会和DEBUG冲突,貌似没什么用,屏蔽又会报错 GPIO_INIT(); // USART_INIT(); // stm32_dmaSetup(); stm32_TimerSetup(); //RTC_Config(); //I2C_Configuration(); stm32_IwdgSetup(); // ADC_CH_DMA_Config(); // EXTIX_Init(); } /** ****************************************************************************** * @file PWR_STOP/stm32f0xx_it.c * @author MCD Application Team * @version V1.0.1 * @date 11-October-2013 * @brief Main Interrupt Service Routines. * This file provides template for all exceptions handler and * peripherals interrupt service routine. ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2> * * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "MM32F031xxn.h" #include "user.h" #include "main.h" //************STM32F1函数以及变量定义******************************************* //****************************************************************************** /** * @brief This function handles NMI exception. * @param None * @retval None */ void NMI_Handler(void) { } /** * @brief This function handles Hard Fault exception. * @param None * @retval None */ void HardFault_Handler(void) { /* Go to infinite loop when Hard Fault exception occurs */ while (1) { } } /** * @brief This function handles SVCall exception. * @param None * @retval None */ void SVC_Handler(void) { } /** * @brief This function handles PendSVC exception. * @param None * @retval None */ void PendSV_Handler(void) { } /** * @brief This function handles SysTick Handler. * @param None * @retval None */ void SysTick_Handler(void) { // STM_EVAL_LEDToggle(LED3); // TimingDelay--; } //void TIM17_IRQHandler(void) //{ // // TIM17->SR&= ~(1<<0); //清除中断标志;UIF // if(Flag_rx_dma==1) // { // Dma_clear_delay++; // } // if(Dma_clear_delay==7) //RX接收到数据后35ms开始更新dma防止干扰下次接收 // { // DMA_Cmd(DMA1_Channel5, DISABLE); /* Disable DMA1 Channel4 transfer */ // DMA1_Channel5->CNDTR=USART1_RXtotal; // DMA_Cmd(DMA1_Channel5, ENABLE); /* Enable DMA1 Channel4 transfer */ // //DMA1->IFCR|=1<<16; //清除DMA通道4的全部中断标志位; // Dma_clear_delay=0; // Flag_rx_dma=0; // } //} /******************************************************************************/ /* STM32F0xx Peripherals Interrupt Handlers */ /* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ /* available peripheral interrupt handler's name please refer to the startup */ /* file (startup_stm32f0x8.s). */ /******************************************************************************/ /** * @brief This function handles RTC Auto wake-up interrupt request. * @param None * @retval None */ void TIM16_IRQHandler(void) { GPIO_InitTypeDef GPIO_InitStructure; uint16_t temp; TIM16->SR&= ~(1<<0); //清除中断标志;UIF counter_cycle++; if(counter_cycle%2==1) { LED_ON; if(((atm<45)||(atm>155))&&((o2P<450)||(o2P>1550))) { BEEP_ON; } } else { LED_OFF; BEEP_OFF; } if(counter_cycle==20) { TIM14->CR1 = 0; // reset command register 1 TIM14->ARR = 20*FCLK_H_MHZ-1; // 30ms TIM14->CR1 |= 1<<0; // 启动timer2 } // if(rx_flag>3) // { // DMA_Cmd(DMA1_Channel5, DISABLE); /* Disable DMA1 Channel4 transfer */ // DMA1_Channel5->CMAR = (u32)&USART1_RXbuffer; // DMA1_Channel5->CNDTR=USART1_RXtotal; // DMA_Cmd(DMA1_Channel5, ENABLE); /* Enable DMA1 Channel4 transfer */ // } flag_menu = 1; } void TIM14_IRQHandler(void) { uint8_t i; TIM14->SR&= ~(1<<0); //清除中断标志;UIF if(counter_cycle>=20) //重置DMA { DMA_Cmd(DMA1_Channel3, DISABLE); /* Disable DMA1 Channel4 transfer */ DMA1_Channel3->CMAR = (u32)&USART1_RXbuffer; DMA1_Channel3->CNDTR=USART1_RXtotal; DMA_Cmd(DMA1_Channel3, ENABLE); /* Enable DMA1 Channel4 transfer */ } else { DMA_Cmd(DMA1_Channel3, DISABLE); /* Disable DMA1 Channel4 transfer */ } if(sensor_num<64) { on_off(sensor_num); //此处有BUG for(i=0;i<100;i++){}; sensor_num++; //每隔25ms查询一次,如果没有收到数据,则报送 USART1_TXbuffer[0] = 0x11; USART1_TXbuffer[1] = 0x01; USART1_TXbuffer[2] = 0x01; USART1_TXbuffer[3] = 0xED; DMA_Cmd(DMA1_Channel2, DISABLE); DMA1_Channel2->CMAR = (u32)&USART1_TXbuffer; DMA1_Channel2->CNDTR = USART1_TXtotal; //DMA通道的DMA缓存的大小 DMA_Cmd(DMA1_Channel2, ENABLE); } else sensor_num = 0; cntr_tim14++; display_flag = 1; } void TIM3_IRQHandler(void) { TIM3->SR&= ~(1<<0); //清除中断标志;UIF } /** * @brief This function handles DMA1 Channel 1 interrupt request. * @param None * @retval None */ void DMA1_Channel4_5_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_TC4)) { DMA_ClearITPendingBit(DMA1_IT_GL4); //清除DMA通道4的全部中断标志位; DMA_Cmd(DMA1_Channel4, DISABLE); /* Enable DMA1 Channel4 transfer */ } if(DMA_GetITStatus(DMA1_IT_TC5)) { DMA_ClearITPendingBit(DMA1_IT_GL5); // USART_DMACmd(USART1,USART_DMAReq_Tx,DISABLE); //USART1 关闭DMA发送使能; /*--------发送数据前先更新接收DMA防止接收前的干扰*/ } DMA_Cmd(DMA1_Channel5, DISABLE); /* Disable DMA1 Channel4 transfer */ DMA1_Channel5->CMAR = (u32)&USART2_RXbuffer; DMA1_Channel5->CNDTR=USART2_RXtotal; DMA_Cmd(DMA1_Channel5, ENABLE); /* Enable DMA1 Channel4 transfer */ } //------------------------------------------------------------------------------ // DMA1_Channel2 Interrupt Handler ----TIM1_CH1的PWM输入捕获比较; //------------------------------------------------------------------------------ //void DMA1_Channel2_IRQHandler (void) void DMA1_Channel2_3_IRQHandler (void) { uint8_t temp, i; uint16_t temp_o2c; if(DMA_GetITStatus(DMA1_IT_TC2)) { DMA_ClearITPendingBit(DMA1_IT_GL2); //清除DMA通道的中断标志位; DMA_Cmd(DMA1_Channel2, DISABLE); /* Enable DMA1 Channel4 transfer */ } if(DMA_GetITStatus(DMA1_IT_TC3)) { DMA_ClearITPendingBit(DMA1_IT_GL3); //清除DMA通道的中断标志位; rx_flag++; temp = 0; for(i=0; i<12; i++) temp += USART1_RXbuffer[i]; if((temp==0)&&(USART1_RXbuffer[0]==0x16)&&(USART1_RXbuffer[1]==0x09)&&(USART1_RXbuffer[2]==0x01)) { o2c = USART1_RXbuffer[3]*256+USART1_RXbuffer[4]; o2RH = USART1_RXbuffer[5]*256+USART1_RXbuffer[6]; o2t = USART1_RXbuffer[7]*256+USART1_RXbuffer[8]; o2P = USART1_RXbuffer[9]*256+USART1_RXbuffer[10]; rx_flag = 0; } if((display_flag)&&(counter_cycle>20)) { report2_format(); auto2_sending(); display_flag = 0; } } DMA_Cmd(DMA1_Channel3, DISABLE); /* Disable DMA1 Channel4 transfer */ DMA1_Channel3->CMAR = (u32)&USART1_RXbuffer; DMA1_Channel3->CNDTR=USART1_RXtotal; DMA_Cmd(DMA1_Channel3, ENABLE); /* Enable DMA1 Channel4 transfer */ } /*void PPP_IRQHandler(void) { }*/ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 根据上面三个.c文件,增加以下功能串口2是PA2(TX)和PA3(RX),串口1是PA9(TX)和PA10(RX),检测板接收到电脑发送启动指令FF FF 10 00 00 25 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 00 00 FF FF后将连接传感器的串口1波特率设置为9600,DMA接收12个字节,发送4个字节,并打开电源,等待5秒钟后,向每个传感器连续发送2遍11 AA 55 F0,四个字节每遍间隔时间5秒,发送2遍之后重新设置串口1波特率为250000,DMA接收30个字节,发送30个字节.接收到以下指令后浓度封底:0A 0B AA 01 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 01 02 03 04 FF 浓度封底:0A 0B AA 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 01 02 03 04 FF 流量0点校准:FF FF 10 00 00 8E 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 00 00 FF FF 高浓度校准:FF FF 10 00 00 7E 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 42 B7 D1 EC FF FF 流量校准:FF FF 10 00 00 8D 00 1E 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 00 00 FF FF 报送数据:FF FF 10 00 00 22 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 00 00 FF FF 直接通过串口1发送给传感器,并接收传感器回复的数据,数据校验要做好 通过串口2发送给电脑,这个是检测板的代码,其他功能变,只改变,需要改变的部分,屏蔽的部分不要删除,计时用定时器,分别生成三个,c文件
11-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值