分享

如何使用STM32F1/F4驱动CS5463

 goodwangLib 2020-04-15

一,前言

第一篇博客,记录一下我的毕设,写的不好的地方大家见谅。在我的毕设里,其中一个部分用到了一个电能测量的模块CS5463,在淘宝买到的附带程序基本都是51的程序,但是本人用的主控是STM32F4系列的核心版,具体型号是STM32F407ZG(和正点原子探索者是同一块芯片啦),这就面临着要把CS5463的51的驱动代码移植到32上面。

其实我在网上有找过很多别人改写的驱动代码,也花钱买了据说亲测有效的驱动,未果。不是写的很乱,不然就是一点数据都读不出来。刚开始用的时候是从买别人的32驱动中下手,从别人的代码里改错,但是就是一直读到寄存器的值都是0,后来一气之下决定还是一句一句从51那边改驱动过来。

改这个驱动代码,其实最主要要改的便是读写寄存器和芯片初始化的地方,只要芯片的SPI时序对了,SPI能正常通信,芯片初始化成功,便能成功读到各个寄存器的数据。

二、SPI时序,引脚

CS5463这个芯片和单片机通信最主要是通过SPI通信的,芯片还具有一个中断引脚(在51那边的程序里,中断引脚没用上,所以在改到32时,中断引脚依然没接),下面把贴一下该模块的引脚图。
需要接的引脚
在32里面,SPI通信可以使用32硬件的时序,也可以使用软件模拟SPI的时序,本文里驱动SPI是使用软件模拟的方式,我一共用了2块板子成功驱动了这个模块,一个是正点原子F1精英版(主控STM32F103ZE),另一个是正点原子F4探索者板子(主控STM32F407ZG),如果有这两块板子的朋友们可以直接下我的程序到板子上试试。

三、注意事项

有一个需要注意的地方!非常重要! 无论用F1还是F4,也应该说只要是用32,就一定要注意!因为STM32的IO端口是分为输入模式和输出模式的,在SPI通信之中,有DO引脚,这个引脚在端口配置是要设置为输入模式的,(因为使用51,端口配置是不分输入输出的,所以在32里面要极为注意端口配置)。

注意: 目前本人用的工程模板为正点原子的模板,然后库函数里,F1和F4的端口配置也有细微的区别 ,下面也详细介绍一下这个区别。

在F1里面,端口配置如下:
在这里插入图片描述
在F1里,除了DO端口(在图中为PF3)设置为上拉输入(GPIO_Mode_IPU)之外,其他端口设置为推挽输出 (GPIO_Mode_Out_PP),IO的速度统一设置为50Mhz。

在F4里面,端口配置如下:
在这里插入图片描述
在F4里,除了DO端口(在图中为PA3)先设置为普通输入模式(GPIO_Mode_IN),然后设置为上拉模式(GPIO_PuPd_UP)之外;其他端口先设置为普通输出模式(GPIO_Mode_OUT),再设置为推挽输出模式(GPIO_OType_PP),IO的速度统一设置为50Mhz。

从代码中大家可以看出F1和F4的细微区别,但其实原理都一样。

四、驱动代码

我有整理了一下我自己写的F1和F4的一个驱动代码(包含了F1、F4、51的3个完整工程),链接如下:
https://download.csdn.net/download/qq_40955079/11186916

另外还要注意的就是,因为大家使用的电流传感器(电感绕的线圈扎数一般情况都不一样,所以建议大家在电流或者电压比例那个做一个小小的计算),目前贴出来的这个比例是只适用我自己的,比如在测电流函数中的 result = 3.23 * result + 7.62;这一句代码,是我根据我读到的寄存器的值和我实际的电流值用matlab做了拟合而得到的,所以各位在使用各个测量的函数时(比如测电流、电压、功率等),大家都需要自行对这个值与真实值进行校准。

由我看来,改驱动最难的地方便在于芯片是否和单片机通信成功,只要通信成功,单片机可以从芯片中读到值了,只要这个模块不是坏的,之后的数据处理都是小问题,由于电流互感器(这个模块使用的是电感),电压互感器感应到的值和实际值基本呈线性的关系,所以即使不用matlab去拟合得这么精确的函数,自己手算也能算出一个大概值,只要通过从芯片寄存器读到的值与实际值计算一个比例关系即可。

上面bb了这么多,到这个阶段了我就直接贴驱动代码啦,可能有一点点小凌乱。(在此展示F1的驱动代码,使用F4的童鞋按照上面的提示相应的改端口驱动就行啦,大家也可以下载我的完整工程)。如果有什么问题需要一起讨论也可以联系本人QQ呀。(350429078)

#include 'CS_5463.h' u8 RX_Buff[4];//CS5463读写缓冲区#define CS5463_VScale 525 //计算电压比例,220V*250mv/110mv=500V#define CS5463_IScale 500 //计算电流比例 (250/10) #define RST_CS5463 GPIO_Pin_0 #define CS_CS5463 GPIO_Pin_1 #define INT_CS5463 GPIO_Pin_2 #define DO_CS5463 GPIO_Pin_3 #define DI_CS5463 GPIO_Pin_4 #define SCK_CS5463 GPIO_Pin_5 void CS5463_Io_Init(void ){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); //使能F端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_4|GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOF, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin =GPIO_Pin_3;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOF, &GPIO_InitStructure); GPIO_SetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5); } void CS5463_Init(void ){CS5463_Io_Init(); GPIO_WriteBit(GPIOF,RST_CS5463 , Bit_RESET);delay_us(100);GPIO_WriteBit(GPIOF, RST_CS5463, Bit_SET);//发送同步序列 RX_Buff[0] = CMD_SYNC1; RX_Buff[1] = CMD_SYNC1; RX_Buff[2] = CMD_SYNC0; CS5463WriteReg(CMD_SYNC1,RX_Buff); //#define CMD_SYNC1 0XFF //开始串口重新初始化//----------------------//初始化--配置寄存器//相位补偿为PC[6:0]=[0000000];//电流通道增益为Igain=10;//EWA=0;//INT中断为低电平有效IMODE:IINV=[00]//iCPU=0//K[3:0]=[0001] RX_Buff[0] = 0x00; RX_Buff[1] = 0x00; RX_Buff[2] = 0x01; CS5463WriteReg(REG_CONFR,RX_Buff); // #define REG_CONFR 0x40 //配置//----------------------//初始化--操作寄存器 RX_Buff[0] = 0x00; //B0000_0000; RX_Buff[1] = 0x00; //B0000_0000; RX_Buff[2] = 0x60; //B0110_0000; CS5463WriteReg(REG_MODER,RX_Buff); //#define REG_MODER 0x64 //操作模式//初始化--CYCLE COUNT 寄存器,4000 RX_Buff[0] = 0x00; RX_Buff[1] = 0x0F; RX_Buff[2] = 0xA0; //#define REG_CYCCONT 0x4A //一个计算周期的A/D转换数 CS5463WriteReg(REG_CYCCONT,RX_Buff); //初始化--CYCLE COUNT 寄存器,4000//---------------------- RX_Buff[0] = 0xFF; RX_Buff[1] = 0xFF; RX_Buff[2] = 0xFF; CS5463WriteReg(REG_STATUSR,RX_Buff); //初始化--状态寄存器 #define REG_STATUSR 0x5E //状态//---------------------- RX_Buff[0] = 0x80; //开电流、电压、功率测量完毕中断 RX_Buff[1] = 0x00; RX_Buff[2] = 0x80; //开温度测量完毕中断 CS5463WriteReg(REG_MASKR,RX_Buff); //初始化--中断屏蔽寄存器 #define REG_MASKR 0x74 //中断屏蔽//---------------------- RX_Buff[0] = 0x00; RX_Buff[1] = 0x00; RX_Buff[2] = 0x00; CS5463WriteReg(REG_CTRLR,RX_Buff); //初始化--控制寄存器 #define REG_CTRLR 0x78 //控制//---------------------- CS5463CMD(CMD_STARTC); //启动连续转换 #define CMD_STARTC 0XE8 //执行连续计算周期 }void CS5463WriteReg(u8 addr,u8 *p){ u8 i,j; u8 dat;GPIO_WriteBit(GPIOF,CS_CS5463 , Bit_RESET); i = 0; while(i<8) { delay_us(50); GPIO_WriteBit(GPIOF,SCK_CS5463, Bit_RESET); if(addr&0x80) GPIO_WriteBit(GPIOF,DI_CS5463, Bit_SET);elseGPIO_WriteBit(GPIOF,DI_CS5463, Bit_RESET);delay_us(50); GPIO_WriteBit(GPIOF,SCK_CS5463, Bit_SET); //在时钟上升沿,数据被写入CS5463 addr <<= 1; i++; } j = 0; delay_us(50); while(j<3) { dat = *(p+j); i = 0;while(i<8){ delay_us(50); GPIO_WriteBit(GPIOF,SCK_CS5463, Bit_RESET);if(dat&0x80) GPIO_WriteBit(GPIOF,DI_CS5463, Bit_SET);elseGPIO_WriteBit(GPIOF,DI_CS5463, Bit_RESET); delay_us(50);GPIO_WriteBit(GPIOF,SCK_CS5463, Bit_SET); //在时钟上升沿,数据被写入CS5463 dat <<= 1; i++;} delay_us(50); j++; } GPIO_WriteBit(GPIOF,DI_CS5463, Bit_SET);GPIO_WriteBit(GPIOF,CS_CS5463 , Bit_SET); delay_us(50);}void CS5463CMD(u8 cmd){ u8 i;GPIO_WriteBit(GPIOF,SCK_CS5463, Bit_SET);GPIO_WriteBit(GPIOF,CS_CS5463 , Bit_RESET); i=0; while(i<8) { delay_us(50);GPIO_WriteBit(GPIOF,SCK_CS5463, Bit_RESET);if(cmd&0x80) GPIO_WriteBit(GPIOF,DI_CS5463, Bit_SET);elseGPIO_WriteBit(GPIOF,DI_CS5463, Bit_RESET);delay_us(50); GPIO_WriteBit(GPIOF,SCK_CS5463, Bit_SET); //在时钟上升沿,数据被写入CS5463 cmd <<= 1; i++; } delay_us(50); GPIO_WriteBit(GPIOF,DI_CS5463, Bit_SET); GPIO_WriteBit(GPIOF,CS_CS5463 , Bit_SET);}void CS5463ReadReg(u8 addr,u8 *p){ u8 i,j; u8 dat; GPIO_WriteBit(GPIOF,CS_CS5463 , Bit_RESET); addr &= READ_MASK; i = 0; while(i<8) { delay_us(50);GPIO_WriteBit(GPIOF,SCK_CS5463, Bit_RESET); if(addr&0x80) GPIO_WriteBit(GPIOF,DI_CS5463, Bit_SET); elseGPIO_WriteBit(GPIOF,DI_CS5463, Bit_RESET); delay_us(50); GPIO_WriteBit(GPIOF,SCK_CS5463, Bit_SET); addr <<= 1; //在时钟上升沿,数据被写入CS5463 i++; } j = 0;GPIO_WriteBit(GPIOF,DI_CS5463, Bit_SET); while(j<3) { i = 0; dat = 0;while(i<8){delay_us(50);GPIO_WriteBit(GPIOF,SCK_CS5463, Bit_RESET);if(i==7)GPIO_WriteBit(GPIOF,DI_CS5463, Bit_RESET);else GPIO_WriteBit(GPIOF,DI_CS5463, Bit_SET);delay_us(50); dat <<= 1; if(GPIO_ReadInputDataBit(GPIOF,DO_CS5463 )) dat |= 0x01;else dat &= 0xFE;GPIO_WriteBit(GPIOF,SCK_CS5463, Bit_SET);delay_us(50); i++;}*(p+j) = dat; j++; }delay_us(50);GPIO_WriteBit(GPIOF,DI_CS5463, Bit_SET);GPIO_WriteBit(GPIOF,CS_CS5463 , Bit_SET);}/**6************************************************************* 函数名称:CS5463_ResetStatusReg** 函数功能:复位状态寄存器函数** 函数参数:无** 第一次修改时间:无**************************************************************/void CS5463_ResetStatusReg(void){ RX_Buff[0] = 0xFF; RX_Buff[1] = 0xFF; RX_Buff[2] = 0xFF; CS5463WriteReg(0x5E,RX_Buff);//复位状态寄存器 #define REG_STATUSR 0x5E //状态 }u8 CS5463_GetStatusReg(void ){ u8 sta1=0; CS5463ReadReg(0x1E,RX_Buff); //1E 是什么? 状态寄存器 if(RX_Buff[0]&0x80) //检测:电流、电压、功率测量是否完毕 {//检测电流/电压是否超出范围//检测电流有效值/电压有效值/电能是否超出范围if((RX_Buff[0]&0x03)||(RX_Buff[1]&0x70)){ CS5463_ResetStatusReg();//复位状态寄存器}else{ sta1 |= 0x01;//B0000_0001; //这什么意思 还可以这样写吗? PT2017-2-8 分隔符吗? } } if(RX_Buff[2]&0x80) //检测:温度测量是否完毕 { sta1 |=0x02; //B0000_0010; } return(sta1);} u32 CS5463_GetCurrentRMS(){ float G = 0.5,result; u32 temp1; u8 temp,i,j;CS5463ReadReg(REG_IRMSR,RX_Buff); //读取电流有效值 //SndCom1Data(RX_Buff,3); i = 0; result = 0; while(i<3) { temp = RX_Buff[i]; j = 0;while(j<8){ if(temp&0x80){ result += G;} temp <<= 1; j++;G = G/2;} i++; } result = result*CS5463_IScale;//I_Coff; //计算电流值 暂时不用 result *= 1000;//单位mA(毫安) 12345ma result = 3.23 * result + 7.62; temp1 = (u32)result;return temp1; }u32 CS5463_GetPactiveRMS(void ){ float G = 1.0,result; u8 temp,i,j; u32 temp1; CS5463ReadReg(0x14,RX_Buff); //读取有功功率REG_Pactive //SndCom1Data(RX_Buff,3); temp = RX_Buff[0]; if(temp&0x80) //如果为负数,计算原码 { } i = 0; result = 0; while(i<3) { temp = RX_Buff[i]; j = 0;while(j<8){ if(temp&0x80){ result += G;} temp <<= 1; j++;G = G/2;} i++; }// result = result*P_Coff; //计算功率,单位W(瓦特)// result = Vrms*Irms; ////////直接计算功率 result = result*13125; temp1 = (u32)result; return temp1; }u32 CS5463_GetPowerFactor(void){ float G = 1.0,result; u8 temp,i,j; u32 temp1; CS5463ReadReg(0x32,RX_Buff); //读取功率因数 //SndCom1Data(RX_Buff,3); temp = RX_Buff[0]; if(temp&0x80) //如果为负数,计算原码 { RX_Buff[0] = ~RX_Buff[0];//本来为取反+1,这里因为精度的原因,不+1 RX_Buff[1] = ~RX_Buff[1]; RX_Buff[2] = ~RX_Buff[2]; } i = 0; result = 0; while(i<3) { temp = RX_Buff[i]; j = 0;while(j<8){ if(temp&0x80){ result += G;} temp <<= 1; j++;G = G/2;} i++; } result *= 10000; temp1 = (u32)result; return temp1; }u32 CS5463_GetTemperature(void) //温度能显示了 PT2017-2-12{ float G = 128,result; u8 temp,i,j; u32 temp1; CS5463ReadReg(0x26,RX_Buff); //读取温度 是的在这里就读到了温度 //SndCom1Data(RX_Buff,3); temp = RX_Buff[0]; if(temp&0x80) //如果为负数,计算原码 { //负数标志 RX_Buff[0] = ~RX_Buff[0];//本来为取反+1,这里因为精度的原因,不+1 RX_Buff[1] = ~RX_Buff[1]; RX_Buff[2] = ~RX_Buff[2]; } i = 0; result = 0; //这个值是浮点数 先清零 再逐个把0.5的权 数据加进来 while(i<3) { temp = RX_Buff[i];//虽然这个数组定义了4个字节 实际就用了 Buff[0] Buff[1] RX_Buff[2] j = 0;while(j<8){ if(temp&0x80){ result += G;//把0.5的权数据加进来 } temp <<= 1; j++;G = G/2;} i++; } if(result<128) //是的这个result 是 -127,128 这里已经获取了温度浮点值 最多是一个3位数? 还有小数点 { result *= 100; temp1 = (u32)result; //是的 这里就是 例如12523 -----> 125.23 怎么去显示? 如何分离 从8A开始显示 } return temp1; }
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35

  • 36

  • 37

  • 38

  • 39

  • 40

  • 41

  • 42

  • 43

  • 44

  • 45

  • 46

  • 47

  • 48

  • 49

  • 50

  • 51

  • 52

  • 53

  • 54

  • 55

  • 56

  • 57

  • 58

  • 59

  • 60

  • 61

  • 62

  • 63

  • 64

  • 65

  • 66

  • 67

  • 68

  • 69

  • 70

  • 71

  • 72

  • 73

  • 74

  • 75

  • 76

  • 77

  • 78

  • 79

  • 80

  • 81

  • 82

  • 83

  • 84

  • 85

  • 86

  • 87

  • 88

  • 89

  • 90

  • 91

  • 92

  • 93

  • 94

  • 95

  • 96

  • 97

  • 98

  • 99

  • 100

  • 101

  • 102

  • 103

  • 104

  • 105

  • 106

  • 107

  • 108

  • 109

  • 110

  • 111

  • 112

  • 113

  • 114

  • 115

  • 116

  • 117

  • 118

  • 119

  • 120

  • 121

  • 122

  • 123

  • 124

  • 125

  • 126

  • 127

  • 128

  • 129

  • 130

  • 131

  • 132

  • 133

  • 134

  • 135

  • 136

  • 137

  • 138

  • 139

  • 140

  • 141

  • 142

  • 143

  • 144

  • 145

  • 146

  • 147

  • 148

  • 149

  • 150

  • 151

  • 152

  • 153

  • 154

  • 155

  • 156

  • 157

  • 158

  • 159

  • 160

  • 161

  • 162

  • 163

  • 164

  • 165

  • 166

  • 167

  • 168

  • 169

  • 170

  • 171

  • 172

  • 173

  • 174

  • 175

  • 176

  • 177

  • 178

  • 179

  • 180

  • 181

  • 182

  • 183

  • 184

  • 185

  • 186

  • 187

  • 188

  • 189

  • 190

  • 191

  • 192

  • 193

  • 194

  • 195

  • 196

  • 197

  • 198

  • 199

  • 200

  • 201

  • 202

  • 203

  • 204

  • 205

  • 206

  • 207

  • 208

  • 209

  • 210

  • 211

  • 212

  • 213

  • 214

  • 215

  • 216

  • 217

  • 218

  • 219

  • 220

  • 221

  • 222

  • 223

  • 224

  • 225

  • 226

  • 227

  • 228

  • 229

  • 230

  • 231

  • 232

  • 233

  • 234

  • 235

  • 236

  • 237

  • 238

  • 239

  • 240

  • 241

  • 242

  • 243

  • 244

  • 245

  • 246

  • 247

  • 248

  • 249

  • 250

  • 251

  • 252

  • 253

  • 254

  • 255

  • 256

  • 257

  • 258

  • 259

  • 260

  • 261

  • 262

  • 263

  • 264

  • 265

  • 266

  • 267

  • 268

  • 269

  • 270

  • 271

  • 272

  • 273

  • 274

  • 275

  • 276

  • 277

  • 278

  • 279

  • 280

  • 281

  • 282

  • 283

  • 284

  • 285

  • 286

  • 287

  • 288

  • 289

  • 290

  • 291

  • 292

  • 293

  • 294

  • 295

  • 296

  • 297

  • 298

  • 299

  • 300

  • 301

  • 302

  • 303

  • 304

  • 305

  • 306

  • 307

  • 308

  • 309

  • 310

  • 311

  • 312

  • 313

  • 314

  • 315

  • 316

  • 317

  • 318

  • 319

  • 320

  • 321

  • 322

  • 323

  • 324

  • 325

  • 326

  • 327

  • 328

  • 329

  • 330

  • 331

  • 332

  • 333

  • 334

  • 335

  • 336

  • 337

  • 338

  • 339

  • 340

  • 341

  • 342

  • 343

  • 344

  • 345

  • 346

  • 347

  • 348

  • 349

  • 350

  • 351

  • 352

  • 353

  • 354

  • 355

  • 356

  • 357

  • 358

  • 359

  • 360

  • 361

  • 362

  • 363

  • 364

  • 365

  • 366

  • 367

  • 368

  • 369

  • 370

  • 371

  • 372

  • 373

  • 374

  • 375

  • 376

  • 377

  • 378

  • 379

  • 380

  • 381

  • 382

  • 383

  • 384

  • 385

  • 386

  • 387

  • 388

  • 389

  • 390

  • 391

  • 392

  • 393

  • 394

  • 395

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多