- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
您好,我正在尝试重复这个基于 esp8266 的 wifi 婴儿监视器项目: baby monitor project但是我不想在另一个 esp8266 上接收数据,而是想在 pc 上接收数据。我是一名 c# 程序员,我遇到了理解 c/c++ 指针数组如何在这里工作和接收 udp 的问题。
这是 esp8266 接收器源代码,可以正常工作,但它接收到的数据会将它们传递给 DAC。而且我无法弄清楚我在哪里可以只一个一个地读取 esp8266 发射器从 ADC 读取的值。从 ADC 读取的数据也是 12 位的,原始代码的作者使用所有 16 位并进行一些压缩来传输更多数据,而这个压缩部分是我难以理解的部分
#include <Wire.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include "ESP8266mDNS.h"
#include <ArduinoOTA.h>
//#include "wifi_params.h"
const int mySDA = D7;
const int mySCL = D6;
const int AMPLI_MUTE_PIN = D2;
const int AMPLI_SHUTDOWN_PIN = D1;
const int RIGHT_BTN = D3;
const int LEFT_BTN = D4;
const int LED1 = D8;
const int udp_recv_port = 45990;
WiFiUDP udp;
TwoWire i2c;
#define NB_DATA_BUFS 5
uint16_t data_buf[NB_DATA_BUFS][700]; // data buffer, N buffered
unsigned int current_play_data_buf; // current data buf being played
unsigned int play_data_buf_pos; // position in the ADC data buffer
unsigned int current_recv_data_buf; // current data buf being received
bool play_waiting = true;
bool amplifier_stopped = false;
long play_waiting_at;
bool left_btn_pressed;
bool right_btn_pressed;
#define ICACHE_RAM_ATTR __attribute__((section(".iram.text")))
#define twi_sda mySDA
#define twi_scl mySCL
#define twi_dcount 0
#define twi_clockStretchLimit 10
#define SDA_LOW() (GPES = (1 << twi_sda)) //Enable SDA (becomes output and since GPO is 0 for the pin, it will pull the line low)
#define SDA_HIGH() (GPEC = (1 << twi_sda)) //Disable SDA (becomes input and since it has pullup it will go high)
#define SDA_READ() ((GPI & (1 << twi_sda)) != 0)
#define SCL_LOW() (GPES = (1 << twi_scl))
#define SCL_HIGH() (GPEC = (1 << twi_scl))
#define SCL_READ() ((GPI & (1 << twi_scl)) != 0)
static void twi_delay(unsigned char v) {
unsigned int i;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
unsigned int reg;
for (i = 0; i<v; i++) reg = GPI;
#pragma GCC diagnostic pop
}
static inline ICACHE_RAM_ATTR bool twi_write_start(void) {
SCL_HIGH();
SDA_HIGH();
if (SDA_READ() == 0) return false;
SDA_LOW();
return true;
}
static inline ICACHE_RAM_ATTR bool twi_write_stop(void) {
uint32_t i = 0;
SCL_LOW();
SDA_LOW();
SCL_HIGH();
while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit); // Clock stretching
SDA_HIGH();
return true;
}
static inline ICACHE_RAM_ATTR bool twi_write_bit(bool bit) {
uint32_t i = 0;
SCL_LOW();
if (bit) SDA_HIGH();
else SDA_LOW();
twi_delay(twi_dcount + 1);
SCL_HIGH();
while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);// Clock stretching
return true;
}
static inline ICACHE_RAM_ATTR bool twi_read_bit(void) {
uint32_t i = 0;
SCL_LOW();
SDA_HIGH();
twi_delay(twi_dcount + 2);
SCL_HIGH();
while (SCL_READ() == 0 && (i++) < twi_clockStretchLimit);// Clock stretching
bool bit = SDA_READ();
return bit;
}
static inline ICACHE_RAM_ATTR bool twi_write_byte(unsigned char byte) {
unsigned char bit;
for (bit = 0; bit < 8; bit++) {
twi_write_bit(byte & 0x80);
byte <<= 1;
}
return !twi_read_bit();//NACK/ACK
}
static inline ICACHE_RAM_ATTR unsigned char twi_read_byte(bool nack) {
unsigned char byte = 0;
unsigned char bit;
for (bit = 0; bit < 8; bit++) byte = (byte << 1) | twi_read_bit();
twi_write_bit(nack);
return byte;
}
unsigned char inline ICACHE_RAM_ATTR mytwi_writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop) {
unsigned int i;
if (!twi_write_start()) return 4;//line busy
if (!twi_write_byte(((address << 1) | 0) & 0xFF)) {
if (sendStop) twi_write_stop();
return 2; //received NACK on transmit of address
}
for (i = 0; i<len; i++) {
if (!twi_write_byte(buf[i])) {
if (sendStop) twi_write_stop();
return 3;//received NACK on transmit of data
}
}
if (sendStop) twi_write_stop();
i = 0;
while (SDA_READ() == 0 && (i++) < 10) {
SCL_LOW();
SCL_HIGH();
}
return 0;
}
static inline ICACHE_RAM_ATTR uint8_t DAC(uint16_t value)
{
/* value is 76543210 XXXXBA98
per the datasheet for fast write:
1 1 0 0 A2 A1 A0 0 <ACK> 0 0 PD1 PD0 D11 D10 D9 D8 <ACK> D7 D6 D5 D4 D3 D2 D1 D0 <ACK>
*/
uint8_t buf[2] = { (value >> 8) & 0x0F, (value & 0xFF) };
int ret = mytwi_writeTo(0x60, buf, 2, true);
Serial.println(value);
return ret;
}
void ICACHE_RAM_ATTR playsample_isr(void)
{
if (play_waiting) {
return;
}
DAC(data_buf[current_play_data_buf][play_data_buf_pos]);
play_data_buf_pos++;
if (play_data_buf_pos >= sizeof(data_buf[0]) / sizeof(data_buf[0][0])) {
play_data_buf_pos = 0;
current_play_data_buf++;
if (current_play_data_buf == NB_DATA_BUFS) {
current_play_data_buf = 0;
}
if (current_play_data_buf == current_recv_data_buf) {
play_waiting = true;
play_waiting_at = micros();
}
}
}
void ota_onstart(void)
{
// Disable timer when an OTA happens
timer1_detachInterrupt();
timer1_disable();
}
void ota_onprogress(unsigned int sz, unsigned int total)
{
Serial.print("OTA: "); Serial.print(sz); Serial.print("/"); Serial.print(total);
Serial.print("="); Serial.print(100 * sz / total); Serial.println("%");
}
void ota_onerror(ota_error_t err)
{
Serial.print("OTA ERROR:"); Serial.println((int)err);
}
void left_btn_intr()
{
left_btn_pressed = 1;
}
void right_btn_intr()
{
right_btn_pressed = 1;
}
void setup(void)
{
Serial.begin(115200);
Serial.println("I was built on " __DATE__ " at " __TIME__ "");
i2c.begin(mySDA, mySCL);
i2c.setClock(400000);
WiFi.mode(WIFI_STA);
WiFi.begin("valik 2", "299745buhlo");
WiFi.setSleepMode(WIFI_MODEM_SLEEP);
Serial.print("Connecting to wifi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Cnnectd to ");
Serial.println("valik 2");
Serial.print("IP ");
Serial.println(WiFi.localIP());
ArduinoOTA.onStart(ota_onstart);
ArduinoOTA.onError(ota_onerror);
ArduinoOTA.onProgress(ota_onprogress);
ArduinoOTA.setHostname("bb-recv");
ArduinoOTA.begin();
timer1_isr_init();
timer1_attachInterrupt(playsample_isr);
timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
timer1_write(clockCyclesPerMicrosecond() / 16 * 50); //50us = 20 kHz sampling freq
udp.begin(udp_recv_port);
pinMode(AMPLI_MUTE_PIN, OUTPUT);
pinMode(AMPLI_SHUTDOWN_PIN, OUTPUT);
digitalWrite(AMPLI_SHUTDOWN_PIN, 0);
digitalWrite(AMPLI_MUTE_PIN, 0);
pinMode(LEFT_BTN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(LEFT_BTN), left_btn_intr, FALLING);
pinMode(RIGHT_BTN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(RIGHT_BTN), right_btn_intr, FALLING);
pinMode(LED1, OUTPUT);
digitalWrite(LED1, 0);
}
int do_undelta7(const uint8_t *val, int sz, uint16_t *out)
{
// Implement delta 7 decompression.
// First bit = 0 <=> uncompressed 15 bits following
// First bit = 1 <=> 7 bits follow representing delta
// must switch to big endian...
uint16_t last = 0;
uint8_t *ptr = (uint8_t *)&out[0];
const uint8_t *start = ptr;
for (int i = 0; i < sz; i++) {
uint16_t *ptr16 = (uint16_t *)ptr;
const int8_t firstbyte = val[i];
if (firstbyte & 0x80) {
// Delta7 compressed
// byte is CSMMMMMM
int8_t delta = firstbyte & 0x3F;
if (firstbyte & 0x40) {
delta = -delta;
}
const uint16_t value = last + delta;
*ptr16 = value;
ptr += 2;
last = value;
}
else {
// uncompressed -- switch bytes back to LE
*ptr++ = val[i + 1];
*ptr++ = val[i];
last = val[i + 1] | val[i] << 8;
i++;
}
}
return ptr - start;
}
void loop(void)
{
ArduinoOTA.handle();
int sz = udp.parsePacket();
//Serial.println(current_play_data_buf);
if (sz) {
uint8_t buf[sz];
udp.read(&buf[0], sz);
current_recv_data_buf++;
if (current_recv_data_buf == NB_DATA_BUFS) {
current_recv_data_buf = 0;
if (current_recv_data_buf == current_play_data_buf && !play_waiting) {
Serial.println("buffer overflow when receiving");
}
}
do_undelta7(buf, sz, &data_buf[current_recv_data_buf][0]);
if (play_waiting) {
Serial.print("Restarting play, was waiting (us)"); Serial.println(micros() - play_waiting_at);
// Re-enable *then* unmute in that order to avoid pops
digitalWrite(AMPLI_SHUTDOWN_PIN, 1);
digitalWrite(AMPLI_MUTE_PIN, 1);
play_waiting = false;
amplifier_stopped = false;
digitalWrite(LED1, 1);
}
Serial.println("");
}
// If not playing anything, but amplifier is still up
if (!amplifier_stopped && play_waiting) {
if ((micros() - play_waiting_at) > 2000 * 1000) {
// If nothing has been played for two seconds, shut down the amplifier
Serial.println("Shutting down amplifier!");
digitalWrite(AMPLI_SHUTDOWN_PIN, 0);
digitalWrite(AMPLI_MUTE_PIN, 0);
amplifier_stopped = true;
digitalWrite(LED1, 0);
}
}
if (left_btn_pressed) {
left_btn_pressed = 0;
digitalWrite(AMPLI_MUTE_PIN, 0);
digitalWrite(AMPLI_SHUTDOWN_PIN, 0);
}
if (right_btn_pressed) {
digitalWrite(AMPLI_SHUTDOWN_PIN, 1);
digitalWrite(AMPLI_MUTE_PIN, 1);
udp.beginPacket(udp.remoteIP(), 45990);
udp.write("sendnow");
udp.endPacket();
right_btn_pressed = 0;
}
// If the amplifier is stopped, add a delay for power saving
if (amplifier_stopped) {
delay(10);
}
}
这是我尝试将代码转换为适用于 Windows 的 C++。但是我遇到了程序只是卡住而没有任何错误并且没有关闭的问题。
#include "stdafx.h"
#include <winsock2.h>
#include <stdio.h>
#include <cstdint>
#include <ctime>
#pragma comment (lib, "ws2_32.lib")
#define NB_DATA_BUFS 5
uint16_t data_buf[NB_DATA_BUFS][700]; // data buffer, N buffered
unsigned int current_play_data_buf; // current data buf being played
unsigned int play_data_buf_pos; // position in the ADC data buffer
unsigned int current_recv_data_buf; // current data buf being received
bool play_waiting = true;
bool amplifier_stopped = false;
long play_waiting_at;
bool left_btn_pressed;
bool right_btn_pressed;
void InitWinsock()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
}
int do_undelta7(const uint8_t *val, int sz, uint16_t *out)
{
// Implement delta 7 decompression.
// First bit = 0 <=> uncompressed 15 bits following
// First bit = 1 <=> 7 bits follow representing delta
// must switch to big endian...
uint16_t last = 0;
uint8_t *ptr = (uint8_t *)&out[0];
const uint8_t *start = ptr;
for (int i = 0; i < sz; i++) {
uint16_t *ptr16 = (uint16_t *)ptr;
const int8_t firstbyte = val[i];
if (firstbyte & 0x80) {
// Delta7 compressed
// byte is CSMMMMMM
int8_t delta = firstbyte & 0x3F;
if (firstbyte & 0x40) {
delta = -delta;
}
const uint16_t value = last + delta;
*ptr16 = value;
ptr += 2;
last = value;
}
else {
// uncompressed -- switch bytes back to LE
*ptr++ = val[i + 1];
*ptr++ = val[i];
last = val[i + 1] | val[i] << 8;
i++;
}
}
return ptr - start;
}
void DAC(uint16_t value)
{
/* value is 76543210 XXXXBA98
per the datasheet for fast write:
1 1 0 0 A2 A1 A0 0 <ACK> 0 0 PD1 PD0 D11 D10 D9 D8 <ACK> D7 D6 D5 D4 D3 D2 D1 D0 <ACK>
*/
uint8_t buf[2] = { (value >> 8) & 0x0F, (value & 0xFF) };
printf("%u\n", value & 0xFFF);
}
int _tmain(int argc, _TCHAR* argv[])
{
SOCKET socketC;
InitWinsock();
struct sockaddr_in serverInfo;
int len = 2000;
serverInfo.sin_family = AF_INET;
serverInfo.sin_port = htons(45990);
serverInfo.sin_addr.s_addr = inet_addr("192.168.1.105");
socketC = socket(AF_INET, SOCK_DGRAM, 0);
char buffers[16];
ZeroMemory(buffers, sizeof(buffers));
sendto(socketC, buffers, sizeof(IReleaseMarshalBuffers), 0, (sockaddr*)&serverInfo, len);
while (1)
{
sockaddr_in from;
const int paketSize = sizeof(from);
int r = paketSize;
char buffer[paketSize];
sprintf(buffer, "%.7s", "sendnow");
if (strcmp(buffer, "exit") == 0)
break;
recvfrom(socketC, buffer, sizeof(buffer), 0, (sockaddr*)&serverInfo, &len);
uint8_t buf[sizeof(buffer)];
uint8_t * bufeerPntr = (uint8_t*)buffer;
uint8_t * bufPntr = (uint8_t*)buffer;
for(int i=0;i<sizeof(buffer);i++)
{
buf[i] = buffer[i];
}
//udp.read(&buf[0], sizeof(buffer));
current_recv_data_buf++;
if (current_recv_data_buf == NB_DATA_BUFS) {
current_recv_data_buf = 0;
if (current_recv_data_buf == current_play_data_buf && !play_waiting) {
printf("buffer overflow when receiving\n");
}
}
do_undelta7(buf, sizeof(buffer), &data_buf[current_recv_data_buf][0]);
}
closesocket(socketC);
return 0;
}
这是我尝试将解码部分翻译成 C#(C# 对我来说更容易理解),但我不得不使用指针和奇怪的 * 和 & 我难以理解的东西:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class UDPListener
{
private const int listenPort = 45990;
public static int Main()
{
bool done = false;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Parse("192.168.1.3"), listenPort);
string received_data;
int BUFSIZE = 700;
byte[] receive_byte_array;
uint current_recv_data_buf = 1;
while (!done)
{
Console.WriteLine("Waiting for broadcast");
receive_byte_array = listener.Receive(ref groupEP);
Console.WriteLine("Received a broadcast from {0}", groupEP.ToString());
received_data = Encoding.ASCII.GetString(receive_byte_array, 0, receive_byte_array.Length);
unsafe
{
UInt16*[,] data_buf = new UInt16*[5, 700];
int sz = receive_byte_array.Length;
if (sz > 0)
{
byte[] buf = new byte[receive_byte_array.Length];
UInt16* f = stackalloc UInt16[2000];
//udp.read(&buf[0], sz);
buf = receive_byte_array;
current_recv_data_buf++;
UInt16 last = 0;
UInt16* @out1 = stackalloc UInt16[800];
for (int i = 0; i < 800; i++)
{
@out1[i] = (char)i;
}
//UIntPtr* ptr = (UIntPtr*)&@out[0];
UIntPtr* ptr = (UIntPtr*)&@out1[0];
UIntPtr* start = ptr;
for (int i = 0; i < sz; i++)
{
UIntPtr* ptr16 = ptr;
byte firstbyte = buf[i];
if ((firstbyte & 0x80) != 0)
{
// Delta7 compressed
// byte is CSMMMMMM
byte delta = (byte)(firstbyte & 0x3F);
if ((firstbyte & 0x40) != 0)
{
delta = (byte)(0 - delta);
}
UInt16 value = (UInt16)(last + delta);
*ptr16 = (UIntPtr)value;
ptr += 2;
last = value;
}
else
{
*ptr++ = (UIntPtr)buf[i + 1];
*ptr++ = (UIntPtr)buf[i];
last = (UInt16)(buf[i + 1] | buf[i] << 8);
i++;
}
}
for (int i = 0; i < 91; i++)
{
System.Console.WriteLine(@out1[i]);
}
string b = "";
}
}
}
listener.Close();
return 0;
}
} // end of class UDPListener
最佳答案
udp.read(&buf[0], sz);
将接收到的 UDP 数据包复制到缓冲区 buf
。函数 do_undelta7
然后将输入缓冲区中的数据解压缩到输出缓冲区 data_buf[current_recv_data_buf]
。 data_buf
是缓冲区数组。中断 playsample_isr 播放 data_buf
中缓冲区的内容。
关于c# - 将 esp8266 代码(部分)转换为 c/c++ 或 c#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53562803/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!