CAN Immitate

main
syneffort 8 months ago
parent fedccf327f
commit 790b1e62e0
  1. 37
      BusCommPractice/BusCommPracticeConsoleApp/CANs/CANBus.cs
  2. 35
      BusCommPractice/BusCommPracticeConsoleApp/CANs/CANNode.cs
  3. 65
      BusCommPractice/BusCommPracticeConsoleApp/CANs/CanFrame.cs
  4. 53
      BusCommPractice/BusCommPracticeConsoleApp/Program.cs

@ -0,0 +1,37 @@
using BusCommPracticeConsoleApp.Models;
namespace BusCommPracticeConsoleApp.CANs
{
public class CANBus
{
private readonly List<CANNode> _nodes = new List<CANNode>();
private CanFrame _currentFrame = null;
public void AddNode(CANNode node)
{
_nodes.Add(node);
node.ConnectToBus(this);
}
public void SendFrame(CANNode sender, CanFrame frame)
{
if (_currentFrame != null && frame.ID >= _currentFrame.ID)
{
Console.WriteLine("Already higher priority frame is used.");
return;
}
_currentFrame = frame;
Console.WriteLine($"{sender.Name} node send the frame{Environment.NewLine}{frame}");
}
public void CompleteTransmission()
{
if (_currentFrame == null)
return;
Console.WriteLine($"Send 0x{_currentFrame.ID.ToString("X8")} frame complete.");
_currentFrame = null;
}
}
}

@ -0,0 +1,35 @@
namespace BusCommPracticeConsoleApp.CANs
{
public class CANNode
{
public string Name { get; set; }
private CANBus _bus;
public CANNode(string name)
{
Name = name;
}
public void ConnectToBus(CANBus bus)
{
_bus = bus;
}
public void SendMessage(uint id, byte[] data)
{
var frame = new CanFrame(id, false, data);
_bus.SendFrame(this, frame);
}
public void ReceiveFrame(CanFrame frame)
{
if (frame.CRC != frame.CRC)
Console.WriteLine("<{Name}> node CRC check error!");
}
public void AcknowledgeFrame()
{
Console.WriteLine($"<{Name}> node acknowledged.");
}
}
}

@ -0,0 +1,65 @@
using System.Text;
namespace BusCommPracticeConsoleApp.CANs
{
public class CanFrame
{
// Field Define
public bool SOF { get; set; } = true; // Start of Frame (1bit)
public uint ID { get; set; } // Identifier (29bits)
public bool RTR { get; set; } // Remote Transmittion Request (1bit)
public byte DLC { get; set; } // Data Length Code (4bit, 0~8)
public byte[] Data { get; set; } // Data Field (0~8 bytes)
public ushort CRC { get; set; } // Cyclic Redundancy Check (15bits)
public bool ACK { get; set; } // Acknowledge (1bit)
public byte EOF { get; set; } // End of Frame (7bits, all 1)
public CanFrame(uint id, bool rtr, byte[] data)
{
if (id > 0x1FFFFFFF) // 29bits check
throw new ArgumentException("The id cannot larger than 29bits.");
if (data.Length > 8)
throw new ArgumentException("The data length cannot larger than 8bytes.");
ID = id;
RTR = rtr;
DLC = (byte)data.Length;
Data = data;
CRC = CalculateCRC();
ACK = false;
}
private ushort CalculateCRC()
{
uint crc = ID;
crc += RTR ? 1u : 0u;
crc += DLC;
foreach (var c in Data)
crc += c;
return (ushort)(crc & 0x7FFF); // 15bits masking
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("=== CAN 2.0B Frame ===");
sb.AppendLine($"SOF: {SOF}");
sb.AppendLine($"ID: 0x{ID:X8}");
sb.AppendLine($"RTR: {RTR}");
sb.AppendLine($"DLC: {DLC}");
sb.Append("Data: ");
for (int i = 0; i < DLC; i++)
{
sb.Append($"0x{Data[i]:X2} ");
}
sb.AppendLine();
sb.AppendLine($"CRC: 0x{CRC:X4}");
sb.AppendLine($"ACK: {ACK}");
sb.AppendLine($"EOF: 0b{Convert.ToString(EOF, 2).PadLeft(7, '0')}");
sb.AppendLine("======================");
return sb.ToString();
}
}
}

@ -1,4 +1,6 @@
using BusCommPracticeConsoleApp.Models;
using System.Text;
using BusCommPracticeConsoleApp.CANs;
using BusCommPracticeConsoleApp.Models;
namespace BusCommPracticeConsoleApp;
@ -6,21 +8,48 @@ class Program
{
static void Main(string[] args)
{
IMessageBus messageBus1= new MessageBus();
IMessageBus messageBus2= new MessageBus();
/**********************
MESSAGE BUS
**********************/
var subscriber1 = new Subscriber(messageBus1, "Sub1");
var subscriber2 = new Subscriber(messageBus1, "Sub2");
var subscriber3 = new Subscriber(messageBus2, "Sub3");
// IMessageBus messageBus1= new MessageBus();
// IMessageBus messageBus2= new MessageBus();
var publisher1 = new Publisher(messageBus1);
var publisher2 = new Publisher(messageBus2);
// var subscriber1 = new Subscriber(messageBus1, "Sub1");
// var subscriber2 = new Subscriber(messageBus1, "Sub2");
// var subscriber3 = new Subscriber(messageBus2, "Sub3");
publisher1.SendMessage("Hello, Bus!");
publisher1.SendMessage("I'm publisher 1");
// var publisher1 = new Publisher(messageBus1);
// var publisher2 = new Publisher(messageBus2);
publisher2.SendMessage("Hello, Bus!");
publisher2.SendMessage("I'm publisher 2");
// publisher1.SendMessage("Hello, Bus!");
// publisher1.SendMessage("I'm publisher 1");
// publisher2.SendMessage("Hello, Bus!");
// publisher2.SendMessage("I'm publisher 2");
/**********************
CAN BUS
**********************/
var bus = new CANBus();
var nodeA = new CANNode("NodeA");
var nodeB = new CANNode("NodeB");
var nodeC = new CANNode("NodeC");
bus.AddNode(nodeA);
bus.AddNode(nodeB);
bus.AddNode(nodeC);
nodeA.SendMessage(0x1ABCDEFF, Encoding.UTF8.GetBytes("PHK"));
nodeB.SendMessage(0x0123F321, new byte[] { 0x55, 0x66, 0x77, 0x88 });
bus.CompleteTransmission();
Thread.Sleep(1000);
nodeC.SendMessage(0x12345678, new byte[] { 0x99, 0xAA, 0xBB, 0xCC });
bus.CompleteTransmission();
Console.ReadLine();
}

Loading…
Cancel
Save