银杏科技有限公司旗下技术文档发布平台 | |||
技术支持电话 | 0379-69926675-801 | ||
技术支持邮件 | Gingko@vip.163.com | ||
版本 | 日期 | 作者 | 修改内容 |
---|---|---|---|
V1.0 | 2020-07-29 | gingko | 初次建立 |
1.在主界面选择File–>New Project 或者直接点击ACCEE TO MCU SELECTOR 2.出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置 在搜索栏的下面,提供的各 种查找方式,可以选择芯片内核,型号,等等,可以帮助你查找芯片。本实验选取的芯片型号为:STM32H750IBKx。 3.配置RCC,使用外部时钟源 4.时基源选择SysTick 5.将PA10,PB7,PB8设置为GPIO_Output 6.引脚模式配置 7.配置串口 在NVIC Settings一栏使能接收中断 引脚配置 8.配置ADC 9.时钟源设置,选择外部高速时钟源,配置为最大主频 10.工程文件的设置, 这里就是工程的各种配置 我们只用到有限几个,其他的默认即可 IDE我们使用的是 MDK V5.27 11.点击Code Generator,进行进一步配置
层数 | OSI模型 | 对应协议或硬件 |
7 | 应用层 | Modbus协议 |
6 | 表示层 | 空 |
5 | 会话层 | 空 |
4 | 传输层 | 空 |
3 | 网络层 | 空 |
2 | 数据链路层 | Modbus串行链路协议 |
1 | 物理层 | RS-485/RS-232 |
RTU模式每个字节(11位)的格式为:
子字节地址 | 功能代码 | 数据 | CRC |
1字节 | 1字节 | 0到252字节 | 2字节 |
* Modbus报文RTU帧
int main(void) { int i; unsigned short int temp[10] = {0}; HAL_Init(); SystemClock_Config(); i2c.initialize(); axp152.initialize(); axp152.set_dcdc1(3500);//[ARM & FPGA] axp152.set_dcdc2(1200);//[FPGA INT] axp152.set_dcdc3(3300);//[DCOUT3] axp152.set_dcdc4(3300);//[DCOUT4] axp152.set_aldo1(3300);//[BK3] axp152.set_aldo2(3300);//[ALDOOUT2] axp152.set_dldo1(3300);//[BK0] axp152.set_dldo2(3300);//[BK1] HAL_Delay(200); MX_GPIO_Init(); MX_USART1_UART_Init(); MX_ADC1_Init(); MX_ADC3_Init(); usart1.initialize(115200); while (1) { if(_500ms_flag == 1){ _500ms_flag = 0; my_adc.read(0); my_adc.read_mux(); temp[0] = my_adc.value[0] * 6 * 100; //5V监控 放大100倍 temp[1] = my_adc.value[5] / 2 * 1000.;//电流监控,取整 temp[2] = my_adc.value[7] * 2 * 100; //3.3V监控 放大100倍 temp[3] = my_adc.value[4] * 2 * 100; //2.5V监控 放大100倍 temp[4] = my_adc.value[6] * 100; //1.2V监控 放大100倍 temp[5] = my_adc.value[2] * 2 * 100; //BK3监控 放大100倍 temp[6] = my_adc.value[1] * 2 * 100; //BK4监控 放大100倍 temp[7] = my_adc.value[3] * 2 * 100; //BK5监控 放大100倍 temp[8] = my_adc.value[8] * 2 * 100; //BK7监控 放大100倍 temp[9] = lm75.read()*100; //温度监控 放大100倍 for(i = 0;i < 10;i ++){ hold_reg[2*i + 0] = temp[i] >> 8; hold_reg[2*i + 1] = temp[i] & 0xFF; } } if(_100ms_flag == 1){ _100ms_flag = 0; modbus.process(); } } }
static char process(void) { unsigned short temp; unsigned char receive_buffer_temp[140]; int counter_temp; //crc if(usart1.counter < 2)return 0; counter_temp = usart1.counter; usart1.counter = 0; memcpy(receive_buffer_temp,usart1.receive_buffer,counter_temp); memset(usart1.receive_buffer,0,counter_temp); temp = receive_buffer_temp[counter_temp - 1] << 8|receive_buffer_temp[counter_temp - 2]; if(crc(receive_buffer_temp,counter_temp - 2) == temp)mb_rsq_pdu(receive_buffer_temp,counter_temp); return 0; } static int mb_rsq_pdu(unsigned char *receive_buffer_temp,int counter_temp) { if(receive_buffer_temp[0] == mb_slave_address){ switch(receive_buffer_temp[1]){ case 1: function_1(receive_buffer_temp); break; case 2: function_2(receive_buffer_temp); break; case 3: function_3(receive_buffer_temp); break; case 4: function_4(receive_buffer_temp); break; case 5: function_5(receive_buffer_temp,counter_temp); break; case 6: function_6(receive_buffer_temp,counter_temp); break; default : mb_excep_rsq_pdu(receive_buffer_temp,1); break; } }else if(receive_buffer_temp[0] == 0){ broadcast(receive_buffer_temp); } return 0; } static int function_1(unsigned char *receive_buffer_temp) { int i; unsigned short cnt; unsigned short coil_num; unsigned short start_address; unsigned short crc_value; int temp; start_address = (receive_buffer_temp[2] << 8) | receive_buffer_temp[3]; coil_num = receive_buffer_temp[4] << 8| receive_buffer_temp[5]; if((start_address + coil_num) > 255){ mb_excep_rsq_pdu(receive_buffer_temp,2); return 1; } receive_buffer_temp[2] = ((coil_num % 8 )? (coil_num / 8 + 1) : (coil_num / 8)); cnt = receive_buffer_temp[2] + 5; if(coil_num % 8){ if(coil_num < 8){ for(i = 0;i < coil_num;i ++)temp |= 1 << i; receive_buffer_temp[3] = ((coil[start_address / 8]) >> (start_address % 8) | (coil[start_address / 8 + 1]) << (8 - (start_address % 8))) & temp; }else { for(i = 0;i < receive_buffer_temp[2] - 1;i++)receive_buffer_temp[3 + i] = (coil[i + start_address / 8]) >> (start_address % 8) | (coil[i + start_address / 8 + 1]) << (8 - (start_address % 8)); receive_buffer_temp[3 + i] = (coil[i + start_address / 8] << ((8 - (coil_num % 8 - start_address % 8) % 8)) & 0xff) >> (8 - (coil_num % 8)); } }else { for(i = 0;i < receive_buffer_temp[2];i++)receive_buffer_temp[3 + i] = (coil[i + start_address / 8]) >> (start_address % 8) | (coil[i + start_address / 8 + 1]) << (8 - (start_address % 8)); } crc_value = crc(receive_buffer_temp,cnt - 2); receive_buffer_temp[cnt - 2] = crc_value & 0x00ff; receive_buffer_temp[cnt - 1] = (crc_value >> 8) & 0xff; for(i = 0;i < cnt;i++)usart1.send_byte(receive_buffer_temp[i]); return 0; } static int function_3(unsigned char *receive_buffer_temp) { int i; int cnt; unsigned short int start_address; unsigned short int crc_value; start_address = (receive_buffer_temp[2] << 8) | receive_buffer_temp[3]; receive_buffer_temp[2] = receive_buffer_temp[5] * 2; if(receive_buffer_temp[2] > 100){ //判断最大传输量,防止越界 mb_excep_rsq_pdu(receive_buffer_temp,2); return 1; } if((start_address * 2 + receive_buffer_temp[2]) > 512){ mb_excep_rsq_pdu(receive_buffer_temp,2); return 1; } cnt = receive_buffer_temp[2] + 5; for(i = 0;i < receive_buffer_temp[2];i++)receive_buffer_temp[i + 3] = hold_reg[start_address * 2 + i]; crc_value = crc(receive_buffer_temp,cnt - 2); receive_buffer_temp[cnt - 2] = crc_value & 0x00ff; receive_buffer_temp[cnt - 1] = (crc_value >> 8) & 0xff; for(i = 0;i < cnt;i++)usart1.send_byte(receive_buffer_temp[i]); return 0; } static int function_5(unsigned char *receive_buffer_temp,int counter_temp) { int i; unsigned short start_address; start_address = (receive_buffer_temp[2] << 8) | receive_buffer_temp[3]; if(start_address > 255){ mb_excep_rsq_pdu(receive_buffer_temp,2); return 1; } if((receive_buffer_temp[4] == 0xff) && (receive_buffer_temp[5] == 0x00)){ coil[(start_address / 8)] |= 1 << start_address % 8; }else if((receive_buffer_temp[4] == 0x00) && (receive_buffer_temp[5] == 0x00)){ coil[(start_address / 8)] &= ~(1 << start_address % 8); }else { mb_excep_rsq_pdu(receive_buffer_temp,3); } for(i = 0;i < counter_temp;i++){ usart1.send_byte(receive_buffer_temp[i]); } return 0;
//定义74HC4051片选管脚 #define SEL_A_ON HAL_GPIO_WritePin(GPIOI, SEL_A_Pin, GPIO_PIN_SET) #define SEL_A_OFF HAL_GPIO_WritePin(GPIOI, SEL_A_Pin, GPIO_PIN_RESET) #define SEL_B_ON HAL_GPIO_WritePin(GPIOI, SEL_B_Pin, GPIO_PIN_SET) #define SEL_B_OFF HAL_GPIO_WritePin(GPIOI, SEL_B_Pin, GPIO_PIN_RESET) #define SEL_C_ON HAL_GPIO_WritePin(GPIOI, SEL_C_Pin, GPIO_PIN_SET) #define SEL_C_OFF HAL_GPIO_WritePin(GPIOI, SEL_C_Pin, GPIO_PIN_RESET) //选择测量BK4时片选脚状态 #define CHANNEL_0_ON SEL_C_OFF;\ SEL_B_OFF;\ SEL_A_OFF //选择测量BK3时片选脚状态 #define CHANNEL_1_ON SEL_C_OFF;\ SEL_B_OFF;\ SEL_A_ON //选择测量BK5时片选脚状态 #define CHANNEL_2_ON SEL_C_OFF;\ SEL_B_ON;\ SEL_A_OFF //选择测量2.5V时片选脚状态 #define CHANNEL_3_ON SEL_C_OFF;\ SEL_B_ON;\ SEL_A_ON //选择测量输入电流时片选脚状态 #define CHANNEL_4_ON SEL_C_ON;\ SEL_B_OFF;\ SEL_A_OFF //选择测量1.2V时片选脚状态 #define CHANNEL_5_ON SEL_C_ON;\ SEL_B_OFF;\ SEL_A_ON //选择测量3.3V时片选脚状态 #define CHANNEL_6_ON SEL_C_ON;\ SEL_B_ON;\ SEL_A_OFF //选择测量BK7时片选脚状态 #define CHANNEL_7_ON SEL_C_ON;\ SEL_B_ON;\ SEL_A_ON
void MX_ADC1_Init(void) { ADC_MultiModeTypeDef multimode = {0}; ADC_ChannelConfTypeDef sConfig = {0}; hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16; //16分频 hadc1.Init.Resolution = ADC_RESOLUTION_16B; //ADC转换分辨率16位 hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; //非扫描模式 hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; //关闭 EOC 中断 hadc1.Init.LowPowerAutoWait = DISABLE; //自动低功耗关闭 hadc1.Init.ContinuousConvMode = DISABLE; //关闭连续转换 hadc1.Init.NbrOfConversion = 1; //1个转换在规则序列中 hadc1.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //禁止触发检测 hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; //存到DR寄存器 hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED; //溢出保留上次转换数据 hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; //位数不左移 hadc1.Init.OversamplingMode = DISABLE; //关闭过采样 if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } multimode.Mode = ADC_MODE_INDEPENDENT; //独立模式 if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK) { Error_Handler(); } sConfig.Channel = ADC_CHANNEL_16; //通道16 sConfig.Rank = ADC_REGULAR_RANK_1; //第 1 个序列 sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; //采样时间 sConfig.SingleDiff = ADC_SINGLE_ENDED; //单端输入 sConfig.OffsetNumber = ADC_OFFSET_NONE; //不选择偏移序号 sConfig.Offset = 0; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } void MX_ADC3_Init(void) { ADC_ChannelConfTypeDef sConfig = {0}; hadc3.Instance = ADC3; hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16; hadc3.Init.Resolution = ADC_RESOLUTION_16B; hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE; hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc3.Init.LowPowerAutoWait = DISABLE; hadc3.Init.ContinuousConvMode = DISABLE; hadc3.Init.NbrOfConversion = 1; hadc3.Init.DiscontinuousConvMode = DISABLE; hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; hadc3.Init.Overrun = ADC_OVR_DATA_PRESERVED; hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; hadc3.Init.OversamplingMode = DISABLE; if (HAL_ADC_Init(&hadc3) != HAL_OK) { Error_Handler(); } sConfig.Channel = ADC_CHANNEL_1; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) { Error_Handler(); } }
void sort(unsigned short int a[], int n) { int i, j, t; //元素从小到大排列 for (i = 0; i < n - 1; i++) { for (j = 0; j < n - i - 1; j++) { if (a[j] > a[j + 1]) { t = a[j]; a[j] = a[j + 1]; a[j + 1] = t; } } } } int read(int channel) { int i; unsigned long int temp = 0; unsigned short int data[50]; ADC_ChannelConfTypeDef channel_config; int channel_remap[2] = {ADC_CHANNEL_16,ADC_CHANNEL_1};//ADC1,16通道 channel_config.Channel = channel_remap[channel]; //通道选择 channel_config.Offset = 0; //偏移量为0 channel_config.Rank = ADC_REGULAR_RANK_1; //第一个序列 channel_config.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; //采样时间 channel_config.SingleDiff = ADC_SINGLE_ENDED; //单端输入 channel_config.OffsetNumber = ADC_OFFSET_NONE; //不选择偏移序号 for(i = 0;i < 50;i ++){ if(channel == 0){ //如果通道为0,则使能ADC1 HAL_ADC_ConfigChannel(&hadc1,&channel_config); HAL_ADC_Start(&hadc1); while(!__HAL_ADC_GET_FLAG(&hadc1,ADC_FLAG_EOC)); data[i] = HAL_ADC_GetValue(&hadc1); }else if(channel == 1){ //如果通道为1,则使能ADC3 HAL_ADC_ConfigChannel(&hadc3,&channel_config); HAL_ADC_Start(&hadc3); while(!__HAL_ADC_GET_FLAG(&hadc3,ADC_FLAG_EOC)); data[i] = HAL_ADC_GetValue(&hadc3); } } sort(data,50); for(i = 20;i < 30;i++){ //取ADC排序后的中间10位数值 temp += data[i]; } temp = temp / 10; //取ADC平均值 if(channel == 0){ //读取ADC1的值 my_adc.value[channel] = temp * ADC_REF / 65536; } return temp; } static int read_mux(void) { //打开通道并读取ADC的值 CHANNEL_0_ON; my_adc.value[1] = my_adc.read(1) * ADC_REF / 65536; CHANNEL_1_ON; my_adc.value[2] = my_adc.read(1) * ADC_REF / 65536; CHANNEL_2_ON; my_adc.value[3] = my_adc.read(1) * ADC_REF / 65536; CHANNEL_3_ON; my_adc.value[4] = my_adc.read(1) * ADC_REF / 65536; CHANNEL_4_ON; my_adc.value[5] = my_adc.read(1) * ADC_REF / 65536; CHANNEL_5_ON; my_adc.value[6] = my_adc.read(1) * ADC_REF / 65536; CHANNEL_6_ON; my_adc.value[7] = my_adc.read(1) * ADC_REF / 65536; CHANNEL_7_ON; my_adc.value[8] = my_adc.read(1) * ADC_REF / 65536; return 0; }